【问题标题】:In-memory compilation with more than one class per file每个文件有多个类的内存编译
【发布时间】:2015-09-10 10:35:36
【问题描述】:

首先我要达到的目标:
我想在运行时在内存中动态编译 java 类。基本上使用提供的 Java Compiler API 没什么大不了的,但是当涉及到每个 .java 文件的多个类时,我就迷路了。

到目前为止我得到了什么:
我目前正在使用答案中提供的InMemoryJavaCompiler (Compile code fully in memory with javax.tools.JavaCompiler)

如上所述,每个文件编译单个类没有问题,但我希望能够编译几乎任何有效的 .java 文件。

例如,我尝试编译的文件 (FileOne.java) 如下所示:

package test;
public class FileOne {
    public static void main(String args[]) {
        System.out.println("Hello, World");
    }
}
class Functions {
    public static int test(int x) {
        return -x;
    }
}

当我尝试像InMemoryJavaCompiler.compile("test.FileOne", source) 这样编译这个文件时,我得到一个异常,在被覆盖的类加载器中标记defineClass(...) 行:

java.lang.ClassFormatError: Extra bytes at the end of class file test/FileOne

内部类也存在这个问题,但我猜这只是某种命名/调用问题:

java.lang.NoClassDefFoundError: test/FileOne (wrong name: test/FileOne$Functions)

【问题讨论】:

  • 您确定每个文件可以有超过 1 个类吗?我没有深入研究InMemoryJavaCompiler,但默认情况下每个文件应该只有一个类。
  • 据我所知,java 仅将每个文件的公共类限制为 1。InMemoryJavaCompiler 只是为了向您展示我当前的位置,因为我试图逐步解决这个问题。如果我希望的解决方案有其他方法,我愿意将其切换出去
  • 你考虑过使用ant吗?
  • @nafas 也许我错过了一些东西,但我不确定 Ant 如何提供运行时编译功能,这可能对我的情况有所帮助。如果你能更详细地解释你的想法就好了
  • @ceekay 据我了解,如果您想编译一个项目(在不同文件夹中有多个类等),您可以编写一个通用的 Ant 构建器(build.xml)来编译您的项目,例如如果您的项目风格像 eclipse(src、lib 等)。那么你可以简单地为ant调用ProcessBuilder

标签: java in-memory java-compiler-api


【解决方案1】:

是的,你说得对,如果一个类有内部类或匿名类,InMemoryJavaCompilation 当前在 github 上可用的原样不起作用。我遇到了与您描述的完全相同的问题。

经过长时间的搜索,我找到了JSCC,非常完整。感谢 verhas(github 用户名)开发它并使其可用。我用嵌套类测试了 JSCC,它工作正常。您可以在 Github 上找到代码以及如何使用它。

https://github.com/verhas/jscc

据我了解,InMemoryJavaCompilation 的问题在于它每个类存储一个byte array。但是,编译器会为具有嵌套类或匿名类的类生成多个类。在这种情况下,InMemoryJavaCompilation 仅存储编译器返回的最后一个类,并且可能不是顶级类。因此,您可能会收到java.lang.NoClassDefFoundError。 JSCC 维护一个Byte Array Map 来保存所有类的编译代码。

虽然您很久以前就问过这个问题,但我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多