Am 24.08.2011 01:00, schrieb Arne Vajhøj:
You might find a detailed example useful. There is an article
about "Dynamic Code Generation with Java Compiler API in Java 6"
by Swaminathan Bhaskar at
http://www.scribd.com/doc/56642760/Java-Compiler
The article shows how to compile source from strings to byte arrays.
I have a slightly differentexample - see below.
Arne
====
package test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.i
utputStream;
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);
}
}