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

p_gaard
p_gaard (13.985 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 (1.004.158 point)
Det er en ny feature i Java 1.6.

Jeg har ogsaa nogle eksempler i http://www.eksperten.dk/ (...) 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 (13.985 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 (1.004.158 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 (1.004.158 point)
Du skal kigge på testMemoryMemory !

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

p_gaard
p_gaard (13.985 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 (1.004.158 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 (13.985 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 (13.985 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 (13.985 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 (1.004.158 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 (13.985 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 (1.004.158 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 (13.985 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 (13.985 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 (13.985 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

Java JDK compiler til BlueJ

Oprettet den 3. februar 2012 kl. 14.26
andersmnielsen giver 60 point for svar | Giv et svar »

Selection does not contain a main type

Oprettet den 3. februar 2012 kl. 11.45
Christian_Marcussen giver 200 point for svar | Giv et svar »

Eclipse + Google GWT - problemer!

Oprettet den 2. februar 2012 kl. 20.55
Christian_Marcussen giver 75 point for svar | Giv et svar »

Seneste guides

Den gode bruger
Adgang til NAS-server via WAN
Kollektion af Batch tutorials (FJERNET)
Tilpas din YouTube afspiller


   




Tips & Tricks fra PC World

Teaser billede

Sådan fjerner du pladskrævende metadata fra dine fotos

Det er langt fra altid, at dine billeders metadata såsom kameramodel og geografisk placering er vigtige at bevare. JPG & PNG Stripper kan luge ud i billedfilerne, så de fylder meget mindre....


Anmeldelser fra PC World

Teaser billede

Test: Superlet bærbar med mange muligheder

Toshiba har med Satellite Z830 skabt en af verdens letteste ultrabooks. Den vejer 1,1 kilo, og computeren på 13 tommer ser på papiret ud til at være en oplagt rejsekammerat. Men den lave vægt har...


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Samsung Galaxy S III på vej

Samsungs bedst sælgende smartphone nogensinde får en efterfølger om kort tid.


Nyheder fra Computerworld

Teaser billede

Apple retter hele 51 sikkerhedshuller i Mac OS X

Apple lukker hele 51 sårbarheder i Mac OS X, hvoraf de fleste er kritiske. Se her, hvor hullerne er.


Kurser
Samarbejdspartnere

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