使用JavaCompiler从另一个应用程序中编译类文件后,如何运行它?

时间:2012-10-29 10:34:27

标签: java compilation

我目前有这段代码:

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

1 个答案:

答案 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);