import javax.tools.SimpleJavaFileObject;
import java.net.URI;
public class StringBuilderJavaSource extends SimpleJavaFileObject {
private StringBuilder code;
public StringBuilderJavaSource(String name) {
super(URI.create("string:///" + name.replace(".", "/") + Kind.SOURCE.extension), Kind.SOURCE);
code = new StringBuilder();
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
public void append(String str) {
code.append(str);
code.append("\n");
}
}
import java.util.Map;
public class MapClassLoader extends ClassLoader {
private final Map<String, byte[]> classes;
public MapClassLoader(Map<String, byte[]> classes) {
this.classes = classes;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classBytes = classes.get(name);
if (classBytes == null) {
throw new ClassNotFoundException(name);
}
Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
throw new ClassNotFoundException(name);
}
return cl;
}
}
import java.util.Map;
public class MapClassLoader extends ClassLoader {
private final Map<String, byte[]> classes;
public MapClassLoader(Map<String, byte[]> classes) {
this.classes = classes;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classBytes = classes.get(name);
if (classBytes == null) {
throw new ClassNotFoundException(name);
}
Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
throw new ClassNotFoundException(name);
}
return cl;
}
}
需要一个测试类,我们新建一个接口
public interface IABC {
void main2();
}
重头戏
import javax.tools.*;
import java.io.IOException;
import java.util.*;
public class Test222{
public static void main(String[] args) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<ByteArrayJavaClass> classFileObjects = new ArrayList<>();
DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<>();
JavaFileManager fileManager = compiler.getStandardFileManager(diagnostic, null, null);
fileManager = new ForwardingJavaFileManager<JavaFileManager>(fileManager) {
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
ByteArrayJavaClass arrayJavaClass = new ByteArrayJavaClass(className);
classFileObjects.add(arrayJavaClass);
return arrayJavaClass;
}
};
StringBuilderJavaSource javaSource = new StringBuilderJavaSource("ABC");
javaSource.append("package com.epoch.planning;");
javaSource.append(" public class ABC implements IABC {");
javaSource.append(" public void main2() {");
javaSource.append(" System.out.print(\"我是使用java动态编译的类\");");
javaSource.append(" }");
javaSource.append(" }");
JavaCompiler.CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostic, null, null, Arrays.asList(javaSource));
Boolean result = compilerTask.call();
for (Diagnostic<? extends JavaFileObject> diagnosticDiagnostic : diagnostic.getDiagnostics()) {
System.out.println(diagnosticDiagnostic.getKind() + ": " + diagnosticDiagnostic.getMessage(null));
}
fileManager.close();
if (!result) {
List<Diagnostic<? extends JavaFileObject>> diagnostics = diagnostic.getDiagnostics();
for (Diagnostic<? extends JavaFileObject> diagnostic1 : diagnostics) {
System.out.println(diagnostic1.toString());
break;
}
System.out.println("compile failed!");
}
Map<String, byte[]> byteCodeMap = new HashMap<>();
for (ByteArrayJavaClass classFileObject : classFileObjects) {
byteCodeMap.put(classFileObject.getName().substring(1), classFileObject.getBytes());
}
MapClassLoader loader = new MapClassLoader(byteCodeMap);
IABC abc = (IABC) loader.findClass("com.epoch.planning.ABC").newInstance();
abc.main2();
}
}
失败了会自动打印日志
修改正确即可正确输出
|