Created
March 30, 2014 14:53
-
-
Save chrisvest/9873843 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 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
what if the .java file consists of import statements.
when I tried it showed no such class found?