8

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

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();

您可以JavaSourceFromStringJavadoc获取源代码。

这将非常方便地编译sourceCodeFoo.class当前工作目录中。

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

4

3 回答 3

3

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

于 2010-01-25T03:47:43.120 回答
3

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

如果您使用自己的 JavaFileManager,您将需要处理这种情况。

于 2010-01-25T04:45:15.943 回答
2

JSR 199 API 附带的演示应用程序有一个 in-memory compile-from-string 示例(它确实使用了MemoryFileManager)。也许在这里这里看看它(这些示例虽然有点过时,但需要稍作改动)。也可以检查如何即时编译?Java.net 上的文章。

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

于 2010-01-25T05:01:34.183 回答