适用于Java 5和Java 6的即时内存Java代码编译
如何从Java 5和Java 6中的任意字符串(在内存中)编译java代码,加载它并在其上运行特定方法(预定义)?
在你点燃之前,我查看了现有的实现:
- 大多数人依赖Java 6 Compiler API。
- 那些没有,依靠技巧。
- 是的,我检查了commons-jci。 要么我太密集了,不能理解它是如何工作的,要么就是它没有。
- 我找不到如何向编译器提供当前的类路径(这是非常巨大的)。
- 在有效的实现上(在Java 6中),我找不到如何正确加载内部类(或内部匿名类)。
- 如果整个东西都在内存中,我会非常喜欢它,因为它在多个环境中运行。
我确信之前已经解决了这个问题,但我找不到任何看起来甚至是谷歌半生产质量的东西(除了jci,正如我之前所说,我还没有设法使用)。
编辑:
- 我查看了JavaAssist – 我需要内部类,Java 5.0语言级支持以及使用整个类路径进行编译。 另外,我想动态创建新类。 我可能弄错了,但我找不到如何用JavaAssit做到这一点。
- 我愿意使用基于文件系统的解决方案(调用javac),但我不知道如何划分类路径,也不知道如何使用特殊的类加载器加载文件(不在我的类路径中)回收多次调用。 虽然我知道如何研究它,但我更喜欢现成的解决方案。
Edit2:现在,我满足于BeanShell“评估”。 显然,它完成了我需要它的一切(获取一个字符串,在’当前’类路径的上下文中评估它。它确实错过了一些Java 5特性,但它可以使用枚举(不定义)和编译’generics’(擦除) )类,所以它应该足够我想要的东西。
我不想将答案标记为已被接受,因为我希望能找到更好的解决方案。
Edit3:接受了beanshell建议 – 它确实非常有用。
如果你没有完全依赖编译,可以轻松嵌入像Beanshell,groovy和其他脚本语言这样的解决方案(事实上,java内置了对插入脚本语言的支持,因此你的代码甚至不知道用什么语言脚本写在)
Beanshell应该运行任何100%的java代码IIRC,我相信Groovy可以运行大多数java代码 – 可能全部。
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)
类中的setCustomArguments(String[] pCustomArguments)
来JavacJavaCompilerSettings
。
您也可以查看Janino。
从他们的网站:
Janino是一个编译器,它读取JavaTM表达式,块,类主体,源文件或一组源文件,并生成直接加载和执行的JavaTM字节码。 Janino不是一个开发工具,而是一个用于运行时编译目的的嵌入式编译器,例如表达式评估程序或JSP之类的“服务器页面”引擎。
我目前正在一个相当大的任务关键项目中使用它,它工作得很好
Javassist可能会让您感兴趣
在像Tomcat这样的Web容器中运行,首先生成一个JSP页面,然后调用它。
这也允许您通过简单地覆盖JSP页面而不是让您的类加载器慢慢运行来摆脱旧的类定义。
由于速度或不更改代码库而导致的“内存中”要求是什么?
ECJ Eclipse Java编译器
Eclipse提供并使用自己的编译器而不是javac
- Eclipse编译器在IDE(Eclipse)中使用
- Eclipse编译器也可以用作Eclipse之外的纯批处理编译器
编译源文件
$ java -jar ecj-3.5.2.jar HelloWorld.java