Oprettet man. d. 25. februar 2008 kl. 13:35:47

p_gaard
p_gaard (11.240 point. Point ude: 180)

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);
}
}

}

Skrevet man. d. 25. februar 2008 kl. 15:31:06| #1

arne_v
arne_v (920.372 point)
Det er en ny feature i Java 1.6.

Jeg har ogsaa nogle eksempler i http://www.eksperten.dk/artikler/941 paa
fil->fil og mem->fil.

Men det er en lidt tricky feature.

Vil du have mem->fil eller mem->mem ?

Skrevet man. d. 25. februar 2008 kl. 17:42:25| #2

p_gaard
p_gaard (11.240 point)
Hej Arne,

Da jeg primært står med en tekststreng bestående af f.eks:

(1) public class a {bla.bla.bla..new class b() ...}

og ikke er interesseret i nogle mellemresultater i filer eller nogle class-fil. i den anden ende må det vel være mem>mem.

Tekststrengen (klassen) skal kompileres i mem og dens metode afvikles i mem.

Jeg er yderst interesseret i hvis du har noget kode som kan løse problemet.

(mit næste problem bliver vel så at få klassen a til at se klassen b i kompilerings- og afviklingsøjeblikket)

Skrevet tor. d. 28. februar 2008 kl. 05:36:23| #3

arne_v
arne_v (920.372 point)
Det her eksempel virker hos mig:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
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 JC16 {
    public static void main(String[] args) throws Exception {
        testFileFile();
        testMemoryFile();
        testFileMemory();
        testMemoryMemory();
    }
    public static void testFileFile() throws Exception {
        PrintWriter pw = new PrintWriter(new FileWriter("Temp2.java"));
        pw.println("public class Temp2 {");
        pw.println("    public void test() {");
        pw.println("        System.out.println(\"Temp2 OK\");");
        pw.println("    }");
        pw.println("}");
        pw.close();
        compileFileFile("Temp2.java", System.err);
        Class<?> c = Class.forName("Temp2");
        Object o = c.newInstance();
        c.getMethod("test", new Class[] { }).invoke(o, new Object[] { });
    }
    public static void compileFileFile(String fnm, PrintStream err) {
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diacol = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager sjfm = javac.getStandardFileManager(diacol, null, null);
        CompilationTask compile = javac.getTask(null, sjfm, diacol, Arrays.asList(new String[] { }), null,
                                                sjfm.getJavaFileObjects(new String[] { fnm }));
        boolean status = compile.call();
        if(err != null) {
            err.println("Compile status: " + status);
            for(Diagnostic<? extends JavaFileObject> dia : diacol.getDiagnostics()) {
                err.println(dia);
            }
        }
    }
    public static void testMemoryFile() throws Exception {
        String src = "public class Temp3 { public void test() { System.out.println(\"Temp3 OK\"); } }";
        compileMemoryFile(src, "Temp3", System.err);
        Class<?> c = Class.forName("Temp3");
        Object o = c.newInstance();
        c.getMethod("test", new Class[] { }).invoke(o, new Object[] { });
    }
    public static void compileMemoryFile(String src, String name, PrintStream err) {
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diacol = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager sjfm = javac.getStandardFileManager(diacol, null, null);
        CompilationTask compile = javac.getTask(null, sjfm, diacol, Arrays.asList(new String[] { }), 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);
            }
        }
    }
    public static void testFileMemory() throws Exception {
        PrintWriter pw = new PrintWriter(new FileWriter("Temp4.java"));
        pw.println("public class Temp4 {");
        pw.println("    public void test() {");
        pw.println("        System.out.println(\"Temp4 OK\");");
        pw.println("    }");
        pw.println("}");
        pw.close();
        SpecialClassLoader xcl = new SpecialClassLoader();
        compileFileMemory("Temp4.java", xcl, System.err);
        Class<?> c = Class.forName("Temp4", true, xcl);
        Object o = c.newInstance();
        c.getMethod("test", new Class[] { }).invoke(o, new Object[] { });
    }
    public static void compileFileMemory(String fnm, 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[] { }), null,
                                                sjfm.getJavaFileObjects(new String[] { fnm }));
        boolean status = compile.call();
        if(err != null) {
            err.println("Compile status: " + status);
            for(Diagnostic<? extends JavaFileObject> dia : diacol.getDiagnostics()) {
                err.println(dia);
            }
        }
    }
    public static void testMemoryMemory() throws Exception {
        String src = "public class Temp5 { public void test() { System.out.println(\"Temp5 OK\"); } }";
        SpecialClassLoader xcl = new SpecialClassLoader();
        compileMemoryMemory(src, "Temp5", xcl, System.err);
        Class<?> c = Class.forName("Temp5", true, xcl);
        Object o = c.newInstance();
        c.getMethod("test", new Class[] { }).invoke(o, new Object[] { });
    }
    public static void compileMemoryMemory(String src, 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[] { }), 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 + ".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 + ".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 {
        MemoryByteCode mbc = new MemoryByteCode(name);
        xcl.addClass(name, mbc);
        return mbc;
    }
}

class SpecialClassLoader extends ClassLoader {
    private Map<String,MemoryByteCode> m;
    public SpecialClassLoader() {
        m = new HashMap<String, MemoryByteCode>();
    }
    protected Class<?> findClass(String name) {
        MemoryByteCode mbc = m.get(name);
        return defineClass(name, mbc.getBytes(), 0, mbc.getBytes().length);
    }
    public void addClass(String name, MemoryByteCode mbc) {
        m.put(name, mbc);
    }
}

Skrevet tor. d. 28. februar 2008 kl. 05:36:46| #4

arne_v
arne_v (920.372 point)
Du skal kigge på testMemoryMemory !

Skrevet man. d. 03. marts 2008 kl. 14:50:24| #5

p_gaard
p_gaard (11.240 point)
testMemoryMemory kører fint hos mig. Jeg har dog ikke fået den kompilerede klasse i memory til at åbne objekter af klasser beliggende på disk. Det ville være fint hvis man kunne pege på et sted hvor der ligger en række klasser.

Skrevet man. d. 03. marts 2008 kl. 15:47:06| #6

arne_v
arne_v (920.372 point)
Proev med:

Arrays.asList(new String[] { "-classpath", "/dir/foobar.jar" })

som 4. argument til getTask.

Skrevet tir. d. 04. marts 2008 kl. 20:28:00| #7

p_gaard
p_gaard (11.240 point)
Tak for det, jeg vil pr&#248;ve...

Skrevet man. d. 31. marts 2008 kl. 04:45:40| #8


Skrevet ons. d. 16. april 2008 kl. 11:28:09| #9

p_gaard
p_gaard (11.240 point)
Jeg vil gerne lige lade denne tråd stå åben...

Skrevet ons. d. 13. august 2008 kl. 00:47:12| #10

p_gaard
p_gaard (11.240 point)
Tilbage til denne!. Jeg har i aften fået undersøgt -classpath som 4. qargument til getTask:

Arrays.asList(new String[] { "-classpath", "C:/arb/Java2/pkkcms_231/Hyperlink.class"})

får flg. fejl 

Compile status: false
null
string:///Temp5.java:16: cannot find symbol
symbol  : class Hyperlink
location: class Temp5
string:///Temp5.java:16: cannot find symbol
symbol  : class Hyperlink
location: class Temp5

Hvem kan gennemskue dette?

Skrevet ons. d. 13. august 2008 kl. 02:48:07| #11

arne_v
arne_v (920.372 point)
Den er også forkert.

Arrays.asList(new String[] { "-classpath", "C:/arb/Java2/pkkcms_231"})

eller

Arrays.asList(new String[] { "-classpath", "C:/arb/Java2"})

afhængig af om pkkcms_231 er en package.

Skrevet tor. d. 16. oktober 2008 kl. 23:45:19| #12

p_gaard
p_gaard (11.240 point)
Det kører fint nu, men kun under eclipse. Når jeg kører det under tomcat i mappen pkkcms_lib .../web-inf/pkkcms_lib så får jeg fejlen:

java.lang.NoClassDefFoundError: javax/tools/DiagnosticListener

Denne fejl har jeg forsøgt at tackle ved at på forskellige måder referere til javax og tools, men uden held.

Ved du hvad jeg kan gøre?

Skrevet fre. d. 17. oktober 2008 kl. 00:15:19| #13

arne_v
arne_v (920.372 point)
Kører Tomcat med Java 1.6 som Java version ?

Skrevet fre. d. 17. oktober 2008 kl. 12:39:48| #14

p_gaard
p_gaard (11.240 point)
Jeg har nu sat tomcat til java version jdk1.6.0_010 og fejlen vedr. DiagnosticListener er væk.

Til gengæld får jeg nu:

NullPointerException
      at SpecialClassLoader.findClass(JC16.java:195)
      at java.lang.classLoader.loadClass(ClassLoader.java:307)
      ...
      ...

Skrevet fre. d. 17. oktober 2008 kl. 12:44:49| #15

p_gaard
p_gaard (11.240 point)
Jeg har nu sat tomcat til java version jdk1.6.0_010 og fejlen vedr. DiagnosticListener er væk. Alt fungerer ok når jeg kører fra eclipse.



Til gengæld får jeg nu output i tomcat (det ser ud til at kompileringen er udført med success):

compile-status:true
NullPointerException
      at SpecialClassLoader.findClass(JC16.java:195)
      at java.lang.classLoader.loadClass(ClassLoader.java:307)
      ...
      ...

Skrevet tir. d. 21. oktober 2008 kl. 10:28:46| #16

p_gaard
p_gaard (11.240 point)
Forresten er spørgsmålet besvaret. Det går fint med at oprette klasser i memory, kompilere og kalde en metode. Sidstnævnte må være et apache/tomcat-java problem.

Skriv et indlæg




Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] [img]link til billede[/img]
Web- og emailadresser omdannes automatisk til links

Log ind

   

   

Seneste spørgsmål

Delete row ved hjælp af button på webuijsf:table

Oprettet den 30. juli 2010 kl. 16.31
faksebanditten giver 30 point for svar | Giv et svar »

Javadoc i netbeans til Mac

Oprettet den 28. juli 2010 kl. 18.06
Nimblefingers giver 60 point for svar | Giv et svar »

Show / Hide script

Oprettet den 27. juli 2010 kl. 13.42
mpjc giver 30 point for svar | Giv et svar »

Seneste guides

100% højde med CSS i alle browsere
XML
Autocad / 3D Max / Revit til Salg.





Tips & Tricks fra PC World

Teaser billede

Sådan får du mest ud af batteriet på din bærbare

Batterierne i den bærbare lever sjældent op til forventningerne, men det er ikke altid batteriernes skyld. Se her hvordan du får mest muligt ud af dine batterier.


Anmeldelser fra PC World

Teaser billede

GTX460: Grafikkort med fin ydelse til rimelige penge

De store grafikkort løber med opmærksomheden, men det er i mellemklassen at de gode køb findes. Et af dem er det helt nye Nvidia GTX460. Se kortets resultater her.


Seneste blogindlæg

Teaser billede

Nu kan du slettes

Det sker af og til at en bruger ønsker at slette sin profil her på Eksperten. Det har vi haft svært ved, men nu kan du gøre det nemt og enkelt. Alt du skal gøre er at logge ind, gå ind på...


Nyheder fra PC World

Teaser billede

Test: Stream nye spil til gamle computere

Det er slut med at investere tusindvis af kroner i dyr hardware for at kunne spille de nyeste spil - amerikansk firma lader stor serverfarm klare arbejdet og streamer spillene til dig via nettet....


Nyheder fra Computerworld

Teaser billede

Test din viden med Computerworlds store sommerquiz

4. del: Brug agurketiden til at få opdateret din viden om it-branchen, og test for sjov om kollegerne på ferie eller derhjemme er lige så skarpe. Computerworld quizzer hver uge hele sommeren.



Kurser
Samarbejdspartnere

Udgiver · © 2010 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301