JDK 1.6的JavaCompiler:如何将类字节直接写入byte 数组?

所以我最近了解了JDK 1.6中提供的新JavaCompiler API 。 这使得直接从运行代码将String编译为.class文件变得非常简单:

 String className = "Foo"; String sourceCode = "..."; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); List unitsToCompile = new ArrayList() {{ 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(); 

您可以从Javadoc获取JavaSourceFromString的源代码。

这将非常方便地将sourceCode编译为当前工作目录中的Foo.class

我的问题是 :是否可以直接编译到byte[]数组,并避免完全处理File I / O的混乱?

也许你可以创建自己的javax.tools.JavaFileManager实现类,在那里你将返回自己的javax.tools.FileObject实现,然后将它写入内存而不是磁盘。 因此,对于您的javax.tools.FileObject Writer openWriter() throws IOException的子类, Writer openWriter() throws IOException方法,您将返回java.io.StringWriter 。 所有方法都应该转换为它们的String对应物。

没有标准API将字节码写入字节数组的原因是编译单个Java源文件可能会导致多个字节码文件。 例如,任何具有嵌套/内部/匿名类的源文件都将生成多个字节码文件。

如果您自己滚动JavaFileManager,则需要处理这种情况。

随JSR 199 API一起提供的演示应用程序有一个内存中的字符串编译示例(确实使用了MemoryFileManager )。 也许在这里或这里看一下(虽然这些样品有点过时,但它们需要稍作修改)。 也许可以检查如何动态编译? Java.net上的文章。

PS:我没有看到所有细节,但我认为它不会处理Stephen C提到的案例。