如何在 Java 5 和 Java 6 中从任意字符串(在内存中)编译 Java 代码,加载它并在其上运行特定方法(预定义)?
在你点燃这个之前,我查看了现有的实现:
我确信这个问题以前已经解决了,但我在谷歌上找不到任何看起来甚至是半生产质量的东西(除了jci,正如我之前所说,我还没有设法使用)。
编辑:
编辑2: 目前,我对 BeanShell 的“评估”感到满意。显然它做了我需要它做的一切(获取一个字符串,在“当前”类路径的上下文中评估它。它确实错过了一些 Java 5 功能,但它可以使用枚举(不是定义)和编译的“通用”(已删除) )课程,所以它应该足够满足我想要的了。
我不想将答案标记为已接受,因为我确实希望出现更好的解决方案。
Edit3:接受了 beanshell 建议 - 它确实非常有效。
JCI 看起来不错。此代码片段应该是您的基础:
JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");
MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());
MemoryResourceStore mrs = new MemoryResourceStore();
CompilationResult result = compiler.compile(sources, mrr, mrs);
// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir
有什么理由这不起作用?
MemoryResourceStore
,按照要求将编译后的类输出发送到内存。
此外,设置
javac
设置(例如您的情况下的类路径)可以通过 setCustomArguments(String[] pCustomArguments)
类中的
JavacJavaCompilerSettings
来完成。
您可能也想看看 Janino。
来自他们的网站:
Janino 是一个编译器,它读取 JavaTM 表达式、块、类体、源文件或一组源文件,并生成直接加载和执行的 JavaTM 字节码。 Janino 并不是一个开发工具,而是一个用于运行时编译目的的嵌入式编译器,例如表达式求值器或“服务器页面”引擎,如 JSP。
我目前正在一个相当大的关键任务项目中使用它,它工作得很好
如果你没有完全依赖于编译,像 Beanshell、groovy 和其他脚本语言这样的解决方案很容易嵌入(事实上,java 内置了对插入脚本语言的支持,所以你的代码甚至不知道什么)脚本所用的语言)
Beanshell 应该运行任何 100% java 代码 IIRC,并且我相信 Groovy 可以运行大多数 java 代码——可能是全部。
Javassist您可能会感兴趣
在Tomcat等Web容器中运行,首先生成JSP页面,然后调用它。
这还允许您通过简单地覆盖 JSP 页面来摆脱旧的类定义,而不是让您的类加载器慢慢运行满。
“内存中”要求是由于速度还是由于不更改代码库?
Eclipse 提供并使用自己的编译器,而不是 javac
编译源文件
$ java -jar ecj-3.5.2.jar HelloWorld.java