动态编译具体过程参考:https://blog.csdn.net/qq_41432730/article/details/129868058
原文缺失实现类并且有点小问题,下面贴出我的实现:
Main类:
package org.example;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, URISyntaxException {
// 内存直接动态编译
//1. 获取 `JavaCompiler` 实例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//2. 获取 `DiagnosticCollector `实例
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
//3. 获取 `StandardJavaFileManager` 实例
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
//4. 自定义实例
String code = "public class HelloWorld {\n" +
" public static void main(String[] args) {\n" +
" System.out.println(\"Hello, world!\");\n" +
" }\n" +
"}";
JavaFileObject source = new JavaSourceFromString("HelloWorld.java", code);
//5. 创建` CompilationTask` 实例
Iterable<? extends JavaFileObject> compilationUnits = Collections.singletonList(source);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
//6. 调用` CompilationTask `的` call() `方法
boolean success = task.call();
//7. 关闭文件管理器
fileManager.close();
if (success) {
System.out.println("Compilation succeeded.");
//8. 反射使用
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File(".").toURI().toURL()});
Class<?> clazz = classLoader.loadClass("HelloWorld");
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new Object[]{null});
} else {
System.out.println("Compilation failed.");
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.println(diagnostic.getMessage(null));
}
}
}
}
JavaFileObject实现类
package org.example;
import javax.tools.SimpleJavaFileObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
public class JavaSourceFromString extends SimpleJavaFileObject {
private ByteArrayOutputStream byteCode = new ByteArrayOutputStream();
private final CharSequence source;
protected JavaSourceFromString(String baseName, CharSequence source) throws URISyntaxException {
super(new URI(baseName), Kind.SOURCE);
this.source = source;
}
@Override
public CharSequence getCharContent(final boolean ignoreEncodingErrors)
throws UnsupportedOperationException {
if (source == null) {
throw new UnsupportedOperationException();
}
return source;
}
/**
* 编译后会调用这个方法把字节码数据放进byteCode这个输出
*/
@Override
public InputStream openInputStream() {
return new ByteArrayInputStream(getByteCode());
}
@Override
public OutputStream openOutputStream() {
return byteCode;
}
public byte[] getByteCode() {
return byteCode.toByteArray();
}
}