0

我目前有这个代码:

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"); ,所以我希望在运行应用程序时看到这个。

4

1 回答 1

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);
于 2012-10-29T10:48:29.570 回答