如何使用资源中的.class文件动态编译和运行.java文件?

如何使用资源中的.class文件动态编译和运行.java文件?,java,javacompiler,Java,Javacompiler,我试图让我的主类在其控制台(eclipse)中打印Example1类(在参考资料/as.java文件中)的输出,该输出依赖于Example2类。我的想法是为了分级——在javafx应用程序中实现它,该应用程序在使用FileChooser找到的编译类文件上运行测试类(示例1)。我了解了如何使用JavaCompiler,但我不知道如何使用它编译依赖于.class文件的.java文件并执行它 import java.io.File; import java.util.ArrayList; import

我试图让我的主类在其控制台(eclipse)中打印Example1类(在参考资料/as.java文件中)的输出,该输出依赖于Example2类。我的想法是为了分级——在javafx应用程序中实现它,该应用程序在使用FileChooser找到的编译类文件上运行测试类(示例1)。我了解了如何使用JavaCompiler,但我不知道如何使用它编译依赖于.class文件的.java文件并执行它

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class Main {
    private static final String EXAMPLE1 = "resources/Example1.java";
    private static final String EXAMPLE2 = "resources/Example2.class";

    public static void main(String[] args) {

        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> d = new DiagnosticCollector<>();
        StandardJavaFileManager fm = jc.getStandardFileManager(d, null, null);

        List<String> tag = new ArrayList<>();
        tag.add("-classpath");
        tag.add(System.getProperty("java.class.path") + File.pathSeparator + EXAMPLE2);

        File file = new File(EXAMPLE1);
        Iterable<? extends JavaFileObject> cu = fm.getJavaFileObjectsFromFiles(Arrays.asList(file));
        JavaCompiler.CompilationTask task = jc.getTask(null, fm, null, tag, null, cu);

        /*
         * ?
         */
    }
}
示例2在
resources/Example2.class

public class Example2 {
    int x;
    int y;

    Example2(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int sum() {
        return x + y;
    }

    public int mult() {
        return x * y;
    }
}

类路径必须命名包含
Example2.class
的文件夹,而不是文件名本身,因此将第二个
标记更改为
标记。添加(…)
标记。添加(“资源”)

您需要调用
task.call()
来实际执行编译器。然后,编译器将
Example1.class
文件放在
Example1.java
文件旁边

要运行该类,需要使用类路径中的
resources
文件夹设置
ClassLoader
,然后使用反射来获取
Example1
类及其
main
方法

StandardJavaFileManager
URLClassLoader
都是资源,因此您应该使用try-with-resources在使用完它们后将其关闭

以下是工作代码:

JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> d = new DiagnosticCollector<>();
try (StandardJavaFileManager fm = jc.getStandardFileManager(d, null, null)) {

    List<String> tag = new ArrayList<>();
    tag.add("-classpath");
    tag.add("resources");

    File file = new File(EXAMPLE1);
    Iterable<? extends JavaFileObject> cu = fm.getJavaFileObjectsFromFiles(Arrays.asList(file));
    JavaCompiler.CompilationTask task = jc.getTask(null, fm, null, tag, null, cu);
    if (! task.call())
        throw new IllegalStateException("compilation failed");
}

try (URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { new File("resources").toURI().toURL() })) {
    Class<?> example1Class = Class.forName("Example1", true, classLoader);
    Method mainMethod = example1Class.getMethod("main", String[].class);
    if (! Modifier.isStatic(mainMethod.getModifiers()))
        throw new IllegalStateException("main method is not static");
    mainMethod.invoke(null, (Object) new String[0]);
}
如果类已编译,并且具有正确的名称和方法,则标准输出将为:

x:1,y:2
总数:3
mult:2
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> d = new DiagnosticCollector<>();
try (StandardJavaFileManager fm = jc.getStandardFileManager(d, null, null)) {

    List<String> tag = new ArrayList<>();
    tag.add("-classpath");
    tag.add("resources");

    File file = new File(EXAMPLE1);
    Iterable<? extends JavaFileObject> cu = fm.getJavaFileObjectsFromFiles(Arrays.asList(file));
    JavaCompiler.CompilationTask task = jc.getTask(null, fm, null, tag, null, cu);
    if (! task.call())
        throw new IllegalStateException("compilation failed");
}

try (URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { new File("resources").toURI().toURL() })) {
    Class<?> example1Class = Class.forName("Example1", true, classLoader);
    Method mainMethod = example1Class.getMethod("main", String[].class);
    if (! Modifier.isStatic(mainMethod.getModifiers()))
        throw new IllegalStateException("main method is not static");
    mainMethod.invoke(null, (Object) new String[0]);
}