如何动态编译资源中的 运行 .java 文件和 .class 文件?
How do I compile and run .java file with .class file in resource dynamically?
我正在尝试让我的 Main class 在其控制台 (eclipse) 中打印出 Example1 class 的输出(在 resources/ as .java 文件中)这取决于在示例 2 class 上。我出于评分目的有这个想法 - 在 javafx 应用程序中实现它,该应用程序在使用 FileChooser 找到的已编译 class 文件上运行测试 class(示例 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);
/*
* ?
*/
}
}
示例 1 作为 resources/Example1.java
.
中的 .java 文件
public class Example1 {
public static void main(String[] args) {
Example2 ex2 = new Example2(1, 2);
System.out.println("x : " + ex2.x + ", y : " + ex2.y);
System.out.println("sum : " + ex2.sum());
System.out.println("mult : " + ex2.mult());
}
}
Example2 作为 resources/Example2.class
中的 .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;
}
}
class路径必须命名包含 Example2.class
的文件夹,而不是文件名本身,因此将第二个 tag.add(...)
更改为 tag.add("resources")
。
您需要调用 task.call()
才能实际执行编译器。然后编译器会将 Example1.class
文件放在 Example1.java
文件旁边。
到运行和class,需要在class路径下设置一个ClassLoader
和resources
文件夹,然后使用反射获取Example1
class 及其 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]);
}
如果 Example1.java
中有错误,您将得到这样的 STDERR 输出:
resources\Example1.java:3: error: cannot find symbol
xExample2 ex2 = new Example2(1, 2);
^
symbol: class xExample2
location: class Example1
1 error
Exception in thread "main" java.lang.IllegalStateException: compilation failed
at Test.main(Test.java:32)
如果 class 编译,并且具有正确的名称和方法,STDOUT 输出将是:
x : 1, y : 2
sum : 3
mult : 2
我正在尝试让我的 Main class 在其控制台 (eclipse) 中打印出 Example1 class 的输出(在 resources/ as .java 文件中)这取决于在示例 2 class 上。我出于评分目的有这个想法 - 在 javafx 应用程序中实现它,该应用程序在使用 FileChooser 找到的已编译 class 文件上运行测试 class(示例 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);
/*
* ?
*/
}
}
示例 1 作为 resources/Example1.java
.
public class Example1 {
public static void main(String[] args) {
Example2 ex2 = new Example2(1, 2);
System.out.println("x : " + ex2.x + ", y : " + ex2.y);
System.out.println("sum : " + ex2.sum());
System.out.println("mult : " + ex2.mult());
}
}
Example2 作为 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;
}
}
class路径必须命名包含 Example2.class
的文件夹,而不是文件名本身,因此将第二个 tag.add(...)
更改为 tag.add("resources")
。
您需要调用 task.call()
才能实际执行编译器。然后编译器会将 Example1.class
文件放在 Example1.java
文件旁边。
到运行和class,需要在class路径下设置一个ClassLoader
和resources
文件夹,然后使用反射获取Example1
class 及其 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]);
}
如果 Example1.java
中有错误,您将得到这样的 STDERR 输出:
resources\Example1.java:3: error: cannot find symbol
xExample2 ex2 = new Example2(1, 2);
^
symbol: class xExample2
location: class Example1
1 error
Exception in thread "main" java.lang.IllegalStateException: compilation failed
at Test.main(Test.java:32)
如果 class 编译,并且具有正确的名称和方法,STDOUT 输出将是:
x : 1, y : 2
sum : 3
mult : 2