1、使用JavaCompiler
位于javax.tools的JavaCompiler类提供了从程序调用 Java™ 编程语言编译器的接口。
编译器可能会在编译期间生成诊断信息(例如,错误消息)。 如果提供了诊断侦听器,则诊断将提供给侦听器。 如果未提供侦听器,则诊断将被格式化为未指定的格式并写入默认输出,即 System.err,除非另有说明。 即使提供了诊断侦听器,某些诊断也可能不适合诊断,并将被写入默认输出。
编译器工具有一个关联的标准文件管理器,它是工具本机(或内置)的文件管理器。 标准文件管理器可以通过调用getStandardFileManager 获得。
重用文件管理器可以潜在地减少扫描文件系统和读取 jar 文件的开销。 尽管可能不会减少开销,但标准文件管理器必须与多个顺序编译一起使用。
这使得以下示例成为推荐的编码模式:
File[] files1 = ... ; // input for first compilation task
File[] files2 = ... ; // input for second compilation task
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits1 = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));
compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();
Iterable<? extends JavaFileObject> compilationUnits2 =
fileManager.getJavaFileObjects(files2); // use alternative method
// reuse the same file manager to allow caching of jar files
compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
fileManager.close();
2、通过Runtime CMD编译
每个 Java 应用程序都有一个 Runtime 类的实例,它允许应用程序与运行应用程序的环境进行交互。 当前运行时可以从 getRuntime 方法中获取。
ProcessBuilder.start() 和 Runtime.exec 方法创建本机进程并返回 Process 子类的实例,该实例可用于控制进程并获取有关它的信息。 Process 类提供了执行来自进程的输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀死)进程的方法。
Runtime runtime=Runtime.getRuntime();
Process process=runtime.exec("java -cp D:/skydance hello");
InputStream inputStream=process.getInputStream();
BufferedReader fBufferedInputStream=new BufferedReader(new InputStreamReader(inputStream));
String string="";
while((string=fBufferedInputStream.readLine())!=null)
{
System.out.println(string);
}
3、运行class
(1)Runtime CMD
通过Runtime进行java命令的执行,运行我们动态编译出来的class。
String runCmd = String.format("java -classpath %s %s", WORK_DIR, CLASS);
Process process = Runtime.getRuntime().exec(runCmd);
int exitCode = process.waitFor();
(2)通过ClassLoader
类加载器是负责加载类的对象。 ClassLoader 类是一个抽象类。 给定类的二进制名称,类加载器应该尝试定位或生成构成类定义的数据。 一种典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。
class NetworkClassLoader extends ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
. . .
}
}