2016-03-26 8 views
0

Ich habe einen Compiler Java-Runtime wie folgt:Malformed Java-Paket Klassennamen beim Laden der Runtime-kompilieren Quelle

public class Compiler { 

    private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    private final Map<String, String> source = new HashMap<String, String>(); 
    private final MemoryFileManager manager = new MemoryFileManager(this.compiler); 

    public void add(String classname, String fileContent) { 
     add(Collections.singletonMap(classname, fileContent)); 
    } 

    public void add(Map<String, String> map) { 
     source.putAll(map); 
    } 

    public void compile() { 
     List<Source> list = new ArrayList<Source>(); 
     for (Map.Entry<String, String> entry : source.entrySet()) { 
      list.add(new Source(entry.getKey(), JavaFileObject.Kind.SOURCE, entry.getValue())); 
     } 
     this.compiler.getTask(null, this.manager, null, null, null, list).call(); 
    } 

    public byte[] getByteCode(String name) { 
     return this.manager.map.get(name).toByteArray(); 
    } 
} 

Und ein begleitendes Beispiel einfache Classloader:

public class SimpleClassLoader extends ClassLoader { 

    private String classname; 
    private byte[] byteCode; 

    public SimpleClassLoader(String classname, byte[] byteCode) { 
     super(SimpleClassLoader.class.getClassLoader()); 
     this.classname = classname; 
     this.byteCode = byteCode; 
    } 

    @Override 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
     if(name.equals(classname)){ 
      return defineClass(name, byteCode, 0, byteCode.length); 
     } 
     return super.findClass(name); 
    } 
} 

Beim Kompilieren und Laden einer Klasse Der Name der resultierenden Klasse wird in den Klassennamen verkettet:

Die Outpu t davon ist unerwartet folgendes:

Package: null 
Name: TestClass 

Wohin gehe ich hier falsch?

Antwort

0

Das example.test Paket war nicht definiert und wurde erforderlich durch werden initialisiert definePackage() innerhalb der Kompilierung-Methode aufrufen:

public void compile() { 
    List<Source> list = new ArrayList<Source>(); 
    for (Map.Entry<PackageClass, String> entry : source.entrySet()) { 
     list.add(new Source(entry.getKey().getCanonicalName(), JavaFileObject.Kind.SOURCE, entry.getValue())); 
     if(getPackage(entry.getKey().getPackage()) == null) { 
      definePackage(entry.getKey().getPackage(), null, null, null, null, null, null, null); 
     } 
    } 
    this.compiler.getTask(null, this.manager, null, null, null, list).call(); 
} 
0

Das Ergebnis von aClass.getName() ist korrekt. Wenn Sie möchten, dass das Programm "TestClass" zurückgibt, sollten Sie aClass.getSimpleName() verwenden.

Ich überprüfe den Quellcode von java.lang.Class.getPackage(). Es ruft Package.getPackage(this) auf, die in Ihrem Fall class.getClassLoader().getPackage("example.test") aufrufen. Da die SimpleClassLoader die Methode protected Class findClass(String name) überschreiben, sollten Sie auch die Methode protected Package getPackage(String name) überschreiben und das Objekt, das Sie erwartet haben, zurückgeben.

+1

Ah, sieht aus wie ich brauche, um das Paket auch festlegen, wann die Klasse über definePackage definieren() –