Den.
Og den lidt forbedrede udgave:
package test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
public class JC {
public static void dynamicCall(String clznam, String src, String cp, String metnam) throws Exception {
SpecialClassLoader xcl = new SpecialClassLoader();
compileMemoryMemory(src, cp, clznam, xcl, System.err);
Class<?> c = Class.forName(clznam, true, xcl);
Object o = c.newInstance();
c.getMethod(metnam, new Class[] { }).invoke(o, new Object[] { });
}
public static void compileMemoryMemory(String src, String cp, String name, SpecialClassLoader xcl, PrintStream err) {
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diacol = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager sjfm = javac.getStandardFileManager(diacol, null, null);
SpecialJavaFileManager xfm = new SpecialJavaFileManager(sjfm, xcl);
CompilationTask compile = javac.getTask(null, xfm, diacol, Arrays.asList(new String[] { "-classpath", cp }), null,
Arrays.asList(new JavaFileObject[] { new MemorySource(name, src) }));
boolean status = compile.call();
if(err != null) {
err.println("Compile status: " + status);
for(Diagnostic<? extends JavaFileObject> dia : diacol.getDiagnostics()) {
err.println(dia);
}
}
}
}
class MemorySource extends SimpleJavaFileObject {
private String src;
public MemorySource(String name, String src) {
super(URI.create("
string:///" + name.replace(".", "/") + ".java"), Kind.SOURCE);
this.src = src;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return src;
}
public OutputStream openOutputStream() {
throw new IllegalStateException();
}
public InputStream openInputStream() {
return new ByteArrayInputStream(src.getBytes());
}
}
class MemoryByteCode extends SimpleJavaFileObject {
private ByteArrayOutputStream baos;
public MemoryByteCode(String name) {
super(URI.create("
byte:///" + name.replace(".", "/") + ".class"), Kind.CLASS);
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
throw new IllegalStateException();
}
public OutputStream openOutputStream() {
baos = new ByteArrayOutputStream();
return baos;
}
public InputStream openInputStream() {
throw new IllegalStateException();
}
public byte[] getBytes() {
return baos.toByteArray();
}
}
class SpecialJavaFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private SpecialClassLoader xcl;
public SpecialJavaFileManager(StandardJavaFileManager sjfm, SpecialClassLoader xcl) {
super(sjfm);
this.xcl = xcl;
}
public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
name = sibling.getName().substring(1, sibling.getName().length() - 5).replace("/", ".");
MemoryByteCode mbc = new MemoryByteCode(name);
xcl.addClass(name, mbc);
return mbc;
}
}
class SpecialClassLoader extends ClassLoader {
private Map<String,MemoryByteCode> m;
public SpecialClassLoader() {
super(SpecialClassLoader.class.getClassLoader());
m = new HashMap<String, MemoryByteCode>();
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
MemoryByteCode mbc = m.get(name);
if(mbc != null) {
return defineClass(name, mbc.getBytes(), 0, mbc.getBytes().length);
} else {
throw new ClassNotFoundException(name);
}
}
public void addClass(String name, MemoryByteCode mbc) {
m.put(name, mbc);
}
}