【问题标题】:JavaCompiler from JDK 1.6: how to write class bytes directly to byte[] array?JDK 1.6 中的 JavaCompiler:如何将类字节直接写入 byte[] 数组?
【发布时间】:2011-01-08 23:00:07
【问题描述】:

所以我最近了解到 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();

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

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

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

【问题讨论】:

    标签: java compilation in-memory jsr199


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        JSR 199 API 附带的演示应用程序有一个内存中 compile-from-string 示例(它确实使用了MemoryFileManager)。也许看看herehere (这些样本虽然有点过时,但需要稍作改动)。也可以查看 Java.net 上的 How to compile on the fly? 文章。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-09-27
          • 2011-09-26
          • 2015-08-04
          • 2012-02-03
          • 1970-01-01
          • 2018-03-18
          • 1970-01-01
          • 2010-12-18
          相关资源
          最近更新 更多