从字符串编译Java源代码而不写入文件

13

这里我找到了一些很好的例子:

// Prepare source somehow.
String source = "package test; public class Test { static { System.out.println(\"hello\"); } public Test() { System.out.println(\"world\"); } }";

// Save source in .java file.
File root = new File("/java"); // On Windows running on C:\, this is C:\java.
File sourceFile = new File(root, "test/Test.java");
sourceFile.getParentFile().mkdirs();
new FileWriter(sourceFile).append(source).close();

// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());

// Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Should print "hello".
Object instance = cls.newInstance(); // Should print "world".
System.out.println(instance); // Should print "test.Test@hashcode".
问题: 是否可以不写入文件而达到完全相同的效果? @编辑: 更确切地说:我知道如何从字符串编译 (重载JavaFileObject),但在这之后,我不知道如何加载类。我可能错过了输出写入部分,但这也是我不想要的事情。 @Edit2 对于任何感兴趣的人,我创建了这个小项目来实现所讨论的功能: https://github.com/Krever/JIMCy

好的,我删除了我的评论,因为实际上它确实写入了一个文件...不过请注意,我自动检测到了包名和类名 ;) - fge
@Joe 不是这样的,这不是 OP 想要的;他知道如何从字符串编译,他想将编译过程的结果写入内存而不是文件中。 - fge
@fge非常正确,我为我的匆忙道歉,我将删除所有其他痕迹 :) - Joe
看一下我发布的第一个链接;我也使用类加载器加载编译结果。 - fge
2个回答

4

好的,所以这里是使用JavaCompilerString输入编译的示例。这个文件是其核心。

这个文件中,我加载已编译的类。您会注意到我还使用正则表达式检测包和类名。


关于输出,如果您想在内存中执行此操作,似乎可以通过实现自己的 JavaFileManager 来实现;但我从未尝试过这样做!
请注意,您可以通过扩展 ForwardingJavaFileManager 轻松调试发生的情况。

@dasblinkenlight 是的,这是可行的,而且这已经是 OP 所做的了;问题在于输出,而不是输入。事实上,我编写了一个编译过程,可以从 String 中读取源代码。 - fge
@Krever 嗯,就像我说的,如果你有一个挂载点到内存文件系统,那么它就在内存中:p 但这当然仍然是一种hack。 - fge
@Krever 再次查看 API,我可能是错的... 看起来有可能将结果放入内存中;然而,我不太清楚如何再次检索并加载它(即,如何启动类加载器)。 - fge
@fge 不错,谢谢你的帮助!现在还有一个从内存中加载这些类的问题,但他们说“万事皆有可能”... :) - Krever
@fge 这个链接显示这是可能的...但可能并不那么简单 :) - Krever
显示剩余8条评论

0

虽然不完全符合您的要求,但Groovy针对Java的库使得从字符串编译和评估表达式变得非常容易。语法不完全相同,但非常类似于Java,因此如果您可以将要编译的字符串更改为Groovy而不是Java,则任务将非常简单。请参见嵌入Groovy以获取代码示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接