JavaCompiler from JDK 1.6: how to write class byte

2019-02-09 18:49发布

So I recently learned of the new JavaCompiler API available in JDK 1.6. This makes it very simple to compile a String to a .class file directly from running code:

String className = "Foo";
String sourceCode = "...";

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

List<JavaSourceFromString> unitsToCompile = new ArrayList<JavaSourceFromString>() 
    {{ 
         add(new JavaSourceFromString(className, sourceCode)); 
    }};

StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
compiler.getTask(null, fileManager, null, null, null, unitsToCompile).call();
fileManager.close();    

ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(className + ".class");
IOUtils.copyStream(fis, bos);

return bos.toByteArray();

You can grab the source to JavaSourceFromString from the Javadoc.

This will very handily compile sourceCode to Foo.class in the current working directory.

My question is: is it possible to compile straight to a byte[] array, and avoid the messiness of dealing with File I/O altogether?

3条回答
祖国的老花朵
2楼-- · 2019-02-09 19:23

The reason that there is no standard API to write bytecodes to a byte array is that compiling a single Java source file may result in multiple bytecode files. For example, any source file with nested / inner / anonymous classes will result in multiple bytecode files.

If you roll your own JavaFileManager, you will need to deal with this situation.

查看更多
闹够了就滚
3楼-- · 2019-02-09 19:31

The demo application that shipped with the JSR 199 API had an in-memory compile-from-string example (which is indeed using a MemoryFileManager). Maybe have a look at it here or here (these samples are a bit outdated though, they will require slight changes). Also maybe check the How to compile on the fly? article on Java.net.

PS: I didn't look at all the details, but I'm don't think it handles the cases mentioned by Stephen C.

查看更多
我只想做你的唯一
4楼-- · 2019-02-09 19:38

Maybe you could create your own javax.tools.JavaFileManager implementing class where you would return your own implementation of javax.tools.FileObject which would then write it out to memory instead to disk. So for your subclass of javax.tools.FileObject Writer openWriter() throws IOException method you would return a java.io.StringWriter. All the methods should be converted to their String counterparts.

查看更多
登录 后发表回答