Java动态加载和编译数据库中存储的外部类
文档: https://docs.oracle.com/javase/7/docs/api/javax/tools/JavaCompiler.html
package inlinecompiler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class InlineCompiler {
public static void main(String[] args) {
//类内容
StringBuilder sb = new StringBuilder(64);
sb.append("package testcompile;\n");
// HelloWorld实现了 DoStuff接口
sb.append("public class HelloWorld implements inlinecompiler.InlineCompiler.DoStuff {\n");
sb.append(" public void doStuff() {\n");
sb.append(" System.out.println(\"Hello world\");\n");
sb.append(" }\n");
sb.append("}\n");
//把类存储到硬盘上
File helloWorldJava = new File("testcompile/HelloWorld.java");
if (helloWorldJava.getParentFile().exists() || helloWorldJava.getParentFile().mkdirs()) {
try {
Writer writer = null;
try {
writer = new FileWriter(helloWorldJava);
writer.write(sb.toString());
writer.flush();
} finally {
try {
writer.close();
} catch (Exception e) {
}
}
/** 编译需要 *********************************************************************************************/
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
// 设置编译所需的 class path
// 因为上面的HelloWorld类实现了 DoStuff接口,所以需要先加载了包含 DoStuff接口的 InlineCompiler.jar
List<String> optionList = new ArrayList<String>();
optionList.add("-classpath");
optionList.add(System.getProperty("java.class.path") + File.pathSeparator + "dist/InlineCompiler.jar");
Iterable<? extends JavaFileObject> compilationUnit
= fileManager.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask(
null,
fileManager,
diagnostics,
optionList,
null,
compilationUnit);
/********************************************************************************************* 编译需要 **/
if (task.call()) {
/** 加载并执行 *************************************************************************************************/
System.out.println("Yipe");
//创建一个新的自定义 class loader,指向HelloWorld类存储的位置
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()});
//通过类名从classloader加载对应的类
Class<?> loadedClass = classLoader.loadClass("testcompile.HelloWorld");
// newInstance
Object obj = loadedClass.newInstance();
// Santity check
if (obj instanceof DoStuff) {
// 强转
DoStuff stuffToDo = (DoStuff)obj;
// 执行方法
stuffToDo.doStuff();
}
/************************************************************************************************* Load and execute **/
} else {
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.format("Error on line %d in %s%n",
diagnostic.getLineNumber(),
diagnostic.getSource().toUri());
}
}
fileManager.close();
} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exp) {
exp.printStackTrace();
}
}
}
public static interface DoStuff {
public void doStuff();
}
}
Loading...