kompilering og kørsel af klasse (i memory)
Hej,Jeg har et godt stykke tid kørt med en løsning hvor mit program skriver en java-klasse ned i en fil, kompilerer denne hvorefter den indlæser/kører vha. classloader. Det må kunne gøres smartere.
Jeg har fundet nedenstående kode som overordnet set skulle kompilere streng i memory og køre en metode, lige hvad jeg skal bruge. Jeg kan ikke få den til at virke. Problemet er en nullpointerexception på linje 90.
mht. linjen "getResult()" er der også noget galt. Evt skal denne fjernes eller der mangler noget.
Er der nogen som kender til problemet?
----------------------------------
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
import javax.tools.JavaCompiler.CompilationTask;
public class OnTheFlyInRAM {
static JavaFileObject generateJavaSourceCode() {
final String source =
"package just.generated;\n" +
"public class Hello {\n" +
"public static void main(String... args) {\n" +
"System.out.println(new Object() {\n" +
"public String toString() {\n" +
"return \"just hello!\";\n" +
"}\n" +
"});\n" +
"}\n" +
"}";
return new SimpleJavaFileObject(toURI("Hello.java"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean
ignoreEncodingErrors)
throws IOException, IllegalStateException,
UnsupportedOperationException {
return source;
}
};
}
static class RAMJavaFileObject extends SimpleJavaFileObject {
RAMJavaFileObject(String name, Kind kind) {
super(toURI(name), kind);
}
ByteArrayOutputStream baos;
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors)
throws IOException, IllegalStateException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public InputStream openInputStream() throws IOException,
IllegalStateException, UnsupportedOperationException {
return new ByteArrayInputStream(baos.toByteArray());
}
@Override
public OutputStream openOutputStream() throws IOException,
IllegalStateException, UnsupportedOperationException {
return baos = new ByteArrayOutputStream();
}
}
getResult()
public static void main(String[] args) throws Exception {
JavaCompiler compiler =
ToolProvider.getSystemJavaCompiler();
final Map<String, JavaFileObject> output =
new HashMap<String, JavaFileObject>();
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
JavaFileManager jfm = new
ForwardingJavaFileManager<StandardJavaFileManager> (
compiler.getStandardFileManager(diagnostics,null,null)) {
@Override
public JavaFileObject getJavaFileForOutput(Location location,
String name,
Kind kind,
FileObject sibling) throws IOException {
JavaFileObject jfo = new RAMJavaFileObject(name, kind);
output.put(name, jfo);
return jfo;
}
};
CompilationTask task = compiler.getTask(
null, jfm, diagnostics, null, null,
Arrays.asList(generateJavaSourceCode()));
if (! task.call()) {
for(Diagnostic dm : diagnostics.getDiagnostics())
System.err.println(dm);
throw new RuntimeException("Compilation failed");
}
System.out.println("generated classes: "+ output.keySet());
ClassLoader cl = new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws
ClassNotFoundException {
JavaFileObject jfo = output.get(name);
if (jfo != null) {
byte[] bytes = ((RAMJavaFileObject)
jfo).baos.toByteArray();
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
};
Class<?> c = Class.forName("just.generated.Hello", false, cl);
c.getMethod("main", String[].class)
.invoke(null, new Object[] {args});
}
private static URI toURI(String name) {
try {
return new URI(name);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}