-
-
Save AmirHossein/96eb4e29d3a21d0431280755f3905c95 to your computer and use it in GitHub Desktop.
Example showing how to generate, compile, load and run Java programs at run-time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.tools.*; | |
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.lang.reflect.Method; | |
import java.net.URI; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Iterator; | |
import java.util.List; | |
public class CodeGenMeta { | |
public static void main(String[] args) throws Exception { | |
String program = "" + | |
"public class CodeGenTest {\n" + | |
" public static void main(String[] args) {\n" + | |
" System.out.println(\"Hello World, from a generated program!\");\n" + | |
" }\n" + | |
"}\n"; | |
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); | |
JavaFileObject compilationUnit = | |
new StringJavaFileObject("CodeGenTest", program); | |
SimpleJavaFileManager fileManager = | |
new SimpleJavaFileManager(compiler.getStandardFileManager(null, null, null)); | |
JavaCompiler.CompilationTask compilationTask = compiler.getTask( | |
null, fileManager, null, null, null, Arrays.asList(compilationUnit)); | |
compilationTask.call(); | |
CompiledClassLoader classLoader = | |
new CompiledClassLoader(fileManager.getGeneratedOutputFiles()); | |
Class<?> codeGenTest = classLoader.loadClass("CodeGenTest"); | |
Method main = codeGenTest.getMethod("main", String[].class); | |
main.invoke(null, new Object[]{null}); | |
} | |
private static class StringJavaFileObject extends SimpleJavaFileObject { | |
private final String code; | |
public StringJavaFileObject(String name, String code) { | |
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), | |
Kind.SOURCE); | |
this.code = code; | |
} | |
@Override | |
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { | |
return code; | |
} | |
} | |
private static class ClassJavaFileObject extends SimpleJavaFileObject { | |
private final ByteArrayOutputStream outputStream; | |
private final String className; | |
protected ClassJavaFileObject(String className, Kind kind) { | |
super(URI.create("mem:///" + className.replace('.', '/') + kind.extension), kind); | |
this.className = className; | |
outputStream = new ByteArrayOutputStream(); | |
} | |
@Override | |
public OutputStream openOutputStream() throws IOException { | |
return outputStream; | |
} | |
public byte[] getBytes() { | |
return outputStream.toByteArray(); | |
} | |
public String getClassName() { | |
return className; | |
} | |
} | |
private static class SimpleJavaFileManager extends ForwardingJavaFileManager { | |
private final List<ClassJavaFileObject> outputFiles; | |
protected SimpleJavaFileManager(JavaFileManager fileManager) { | |
super(fileManager); | |
outputFiles = new ArrayList<ClassJavaFileObject>(); | |
} | |
@Override | |
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { | |
ClassJavaFileObject file = new ClassJavaFileObject(className, kind); | |
outputFiles.add(file); | |
return file; | |
} | |
public List<ClassJavaFileObject> getGeneratedOutputFiles() { | |
return outputFiles; | |
} | |
} | |
private static class CompiledClassLoader extends ClassLoader { | |
private final List<ClassJavaFileObject> files; | |
private CompiledClassLoader(List<ClassJavaFileObject> files) { | |
this.files = files; | |
} | |
@Override | |
protected Class<?> findClass(String name) throws ClassNotFoundException { | |
Iterator<ClassJavaFileObject> itr = files.iterator(); | |
while (itr.hasNext()) { | |
ClassJavaFileObject file = itr.next(); | |
if (file.getClassName().equals(name)) { | |
itr.remove(); | |
byte[] bytes = file.getBytes(); | |
return super.defineClass(name, bytes, 0, bytes.length); | |
} | |
} | |
return super.findClass(name); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment