我目前有这段代码:
private void compile(){
List<File> files = getListOfJavaFiles();
//JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//compiler.run(null, null, null, srcDirectory.getPath()+"/Main.java");
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits1 =
fileManager.getJavaFileObjectsFromFiles(files);
List<String> optionList = new ArrayList<String>();
// set compiler's classpath to be same as the runtime's
optionList.addAll(Arrays.asList("-classpath",System.getProperty("java.class.path")));
//need to add options here.
compiler.getTask(null, fileManager, null, optionList, null, compilationUnits1).call();
//compiler.run(null, null, null, srcDirectory.getPath()+"/Main.java");
// fileManager.close();
}
但我现在陷入困境,试图让它实际运行已编译的文件。 我在控制台中看不到这个输出,但是在我编译成功的Main.java文件中(我可以看到.class文件),我已经把“System.out.println(”Main class is running“); ,所以我希望在运行应用程序时看到这一点。
答案 0 :(得分:1)
您可以创建一个URLClassLoader来加载新编译的类,或者您可以查看我编写的库,该库将在内存中编译并默认加载到当前的类加载器中。
http://vanillajava.blogspot.co.uk/2010/11/more-uses-for-dynamic-code-in-java.html
如果您已生成代码,它会在调试时将文件保存到源目录,这样您就可以进入生成的代码(否则它会在内存中执行所有操作)
您只能以这种方式加载一个类,所以如果您需要加载许多版本,我建议您实现一个接口并每次更改该类的名称。
// this writes the file to disk only when debugging is enabled.
CachedCompiler cc = CompilerUtils.DEBUGGING ?
new CachedCompiler(new File(parent, "src/test/java"), new File(parent, "target/compiled")) :
CompilerUtils.CACHED_COMPILER;
String text = "generated test " + new Date();
Class fooBarTeeClass = cc.loadFromJava("eg.FooBarTee", "package eg;\n" +
'\n' +
"import eg.components.BarImpl;\n" +
"import eg.components.TeeImpl;\n" +
"import eg.components.Foo;\n" +
'\n' +
"public class FooBarTee{\n" +
" public final String name;\n" +
" public final TeeImpl tee;\n" +
" public final BarImpl bar;\n" +
" public final BarImpl copy;\n" +
" public final Foo foo;\n" +
'\n' +
" public FooBarTee(String name) {\n" +
" // when viewing this file, ensure it is synchronised with the copy on disk.\n" +
" System.out.println(\"" + text + "\");\n" +
" this.name = name;\n" +
'\n' +
" tee = new TeeImpl(\"test\");\n" +
'\n' +
" bar = new BarImpl(tee, 55);\n" +
'\n' +
" copy = new BarImpl(tee, 555);\n" +
'\n' +
" // you should see the current date here after synchronisation.\n" +
" foo = new Foo(bar, copy, \"" + text + "\", 5);\n" +
" }\n" +
'\n' +
" public void start() {\n" +
" }\n" +
'\n' +
" public void stop() {\n" +
" }\n" +
'\n' +
" public void close() {\n" +
" stop();\n" +
'\n' +
" }\n" +
"}\n");
// add a debug break point here and step into this method.
FooBarTee fooBarTee = new FooBarTee("test foo bar tee");
Foo foo = fooBarTee.foo;
assertNotNull(foo);
assertEquals(text, foo.s);