适用于Java 5和Java 6的即时内存Java代码编译

时间:2009-03-05 20:44:48

标签: java compiler-construction runtime compilation runtime-compilation

如何从Java 5和Java 6中的任意字符串(在内存中)编译java代码,加载它并在其上运行特定方法(预定义)?

在你点燃之前,我查看了现有的实现:

  • 大多数人依赖Java 6 Compiler API。
  • 那些不依赖技巧的人。
  • 是的,我查了一下commons-jci。要么我太密集了,要么无法理解它是如何工作的,要么就是没有。
  • 我找不到如何向编译器提供当前的类路径(这是非常大的)。
  • 关于有效的实现(在Java 6中),我找不到如何正确加载内部类(或内部匿名类)。
  • 如果整个事情都在内存中,我会非常喜欢它,因为它在多个环境中运行。

我确信之前已经解决了这个问题,但我找不到任何看起来甚至是谷歌半生产质量的东西(除了jci,正如我之前所说,我还没有设法使用)

编辑:

  • 我查看了JavaAssist - 我需要内部类,Java 5.0语言级支持以及使用整个类路径进行编译。另外,我想动态创建新类。一世 可能是错的,但我找不到如何用JavaAssit做到这一点。
  • 我愿意使用基于文件系统的解决方案(调用javac),但我不知道如何划分类路径,也不知道如何使用特殊的类加载器加载文件(不在我的类路径中)可以回收多次调用。虽然我知道如何研究它,但我更喜欢现成的解决方案。

EDIT2: 现在,我对BeanShell“评估”感到满意。显然它完成了我需要的所有东西(获取一个字符串,在'当前'类路径的上下文中评估它。它确实错过了一些Java 5特性,但它可以使用枚举(不定义)和编译'泛型'(擦除) )类,所以它应该足够我想要的。

我不想将答案标记为已接受,因为我希望找到更好的解决方案。

Edit3:接受了beanshell建议 - 它确实非常有效。

6 个答案:

答案 0 :(得分:9)

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设置,例如您的案例中的类路径,可以通过JavacJavaCompilerSettings课程中的setCustomArguments(String[] pCustomArguments)来完成。

答案 1 :(得分:6)

您也可以查看Janino。

从他们的网站:

Janino是一个编译器,它读取JavaTM表达式,块,类主体,源文件或一组源文件,并生成直接加载和执行的JavaTM字节码。 Janino不是一个开发工具,而是一个用于运行时编译目的的嵌入式编译器,例如:表达式评估程序或“服务器页面”引擎,如JSP。

http://www.janino.net/

我目前正在一个非常大的任务关键项目中使用它,它运行得很好

答案 2 :(得分:3)

如果你没有完全依赖于编译,可以轻松嵌入像Beanshell,groovy和其他脚本语言这样的解决方案(实际上,java内置了对插入脚本语言的支持,因此你的代码甚至都没有知道脚本写的是什么语言)

Beanshell应该运行任何100%的java代码IIRC,我相信Groovy可以运行大多数java代码 - 可能全部。

答案 3 :(得分:1)

Javassist可能会让您感兴趣

答案 4 :(得分:0)

在像Tomcat这样的Web容器中运行,首先生成一个JSP页面,然后调用它。

这也允许您通过简单地覆盖JSP页面而不是让您的类加载器缓慢运行来摆脱旧的类定义。

由于速度或不更改代码库而导致的“内存中”要求是什么?

答案 5 :(得分:0)

ECJ Eclipse Java Compiler

Eclipse提供并使用自己的编译器而不是javac

  • Eclipse编译器在IDE(Eclipse)
  • 中使用
  • Eclipse编译器也可以用作纯批处理编译器 在Eclipse之外

编译源文件

$ java -jar ecj-3.5.2.jar HelloWorld.java