我曾经JavaCompiler
编译过一个即时生成的类。编译任务成功。然后我尝试使用加载编译的类Class.forName("MyClass")
;它以 ClassNotFoundException 失败。这样做是否存在已知问题?
package com.amir.method;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.tools.*;
public class MethodGenerator {
private final static MethodGenerator INSTANCE = new MethodGenerator();
private MethodGenerator() {
}
public static MethodGenerator get() {
return INSTANCE;
}
public static void main(String[] args) {
final Class<?> clz = MethodGenerator.get().compile("Foo", "doIt"); //<- args ignored for now
}
public Class compile(final String className,
final String methodName) {
try {
return doCompile(className, methodName);
} catch(final Exception e) {
throw new RuntimeException(this.toString(), e);
}
}
private Class doCompile(final String className,
final String methodName) throws IOException, ClassNotFoundException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class HelloWorld {");
out.println(" public static void main(String args[]) {");
out.println(" System.out.println(\"This is in another java file\");");
out.println(" }");
out.println("}");
out.close();
final JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());
final Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
final String classPath = System.getProperty("java.class.path") + File.pathSeparator;
final String bootClassPath = System.getProperty("sun.boot.class.path") + File.pathSeparator;
final List<String> options = new ArrayList<String>();
options.add("-classpath");
final StringBuilder builder = new StringBuilder();
builder.append(classPath);
builder.append(bootClassPath);
final URLClassLoader urlClassLoader = (URLClassLoader) ClassLoaderResolver.getClassLoader();
for (final URL url : urlClassLoader.getURLs()) {
builder.append(url.getFile()).append(File.pathSeparator);
}
final int lastIndexOfColon = builder.lastIndexOf(File.pathSeparator);
builder.replace(lastIndexOfColon, lastIndexOfColon + 1, "");
options.add(builder.toString());
final JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, options, null, compilationUnits);
boolean success = task.call();
if(success) {
final Class<?> cls = Class.forName("HelloWorld", true, urlClassLoader);
return cls;
}
return null;
}
class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}