2016-04-14 19 views
4

Ich habe versucht, einige Java-Klassen in einem String mit Java zu kompilieren. Ich habe javax.tools.JavaCompiler verwendet, um die Klassen in den Strings zu kompilieren.Kompilieren zirkuläre Abhängigkeit Klassen mit javax.tools.JavaCompiler

Ich habe Instanzen von SimpleJavaFileObject von einer Subklasse gemacht, die ich von SimpleJavaFileObject gemacht habe.

import javax.tools.SimpleJavaFileObject; 
import java.net.URI; 

public class JavaSourceFromString extends SimpleJavaFileObject { 
    final String code; 

    public JavaSourceFromString(String name, String code) { 
     super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE); 
     this.code = code; 
    } 

    @Override 
     public CharSequence getCharContent(boolean ignoreEncodingErrors) { 
     return code; 
    } 
} 

und ich habe Instanzen dieser Klasse gemacht, hat es zu einem Arraylist, dann bekam die

ToolProvider.SystemJavaCompiler();

und hinzugefügte Kompilierungsoptionen. und dann kompiliert

Iterable<? extends JavaFileObject> fileObjects = jsfsList; 

JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
if (jc == null) throw new Exception("Compiler unavailable"); 

List<String> options = new ArrayList<>(); 
options.add("-d"); 
options.add(Config.getProperty("DESTINATION_PATH")); 
options.add("-classpath"); 

URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
StringBuilder sb = new StringBuilder(); 
for (URL url : urlClassLoader.getURLs()) { 
    sb.append(url.getFile()).append(File.pathSeparator); 
} 
sb.append(PiranhaConfig.getProperty("DESTINATION_PATH")); 
options.add(sb.toString()); 

StringWriter output = new StringWriter(); 
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
if (success) { 
    LOG.info("Class [" + compiledClasses + "] has been successfully compiled"); 
} else { 
    throw new Exception("Compilation failed :" + output); 
} 

Ich habe dies mit 3 Klassen getestet, die Kreisabhängigkeit haben. es gibt den Fehler, dass es das Symbol einer Referenz nicht finden kann. Es scheint, dass dieser Compiler im Gegensatz zu javac jedes Element in der Liste einzeln betrachtet und versucht, jedes einzeln zu kompilieren.

Wie erreiche ich das gleiche Ergebnis wie Javac mit diesem Compiler ?? Jemand bitte zeigen Sie mir in die richtige Richtung :) Danke.

+0

beachten Sie auch, dass diese drei Testklassen Form 3 verschiedene Pakete sind :) –

+0

Kreis Abhängigkeiten zwischen den Paketen sind nicht so eine gute Idee, in erster Linie ... –

+0

Obwohl ich denke, dass die Frage einigermaßen interessant ist, habe ich beschlossen, sie zu schließen: "Fragen, die Debugging-Hilfe suchen (" Warum funktioniert dieser Code nicht? ") Müssen das gewünschte Verhalten, ein spezifisches Problem oder einen Fehler und den kürzesten erforderlichen Code enthalten um es in der Frage selbst zu reproduzieren. Fragen ohne eine klare Problembeschreibung sind für andere Leser nicht nützlich. Siehe: [Wie man ein minimales, vollständiges und überprüfbares Beispiel erstellt] (http://stackoverflow.com/help/mcve). " Können Sie Ihr Beispiel aktualisieren, so dass a) wir es kompilieren können, b) es das Problem reproduziert, c) es spezifische Fehler enthält, die Sie gefunden haben. –

Antwort

0

ich eine Lösung gefunden haben für das Problem,

in den Kompilierungsprozess Ich habe eine ArrayList gemacht, um die SimpleJavaFileObject (Klassen zu kompilieren) Instanzen statt ich habe ad ded eine LinkedList.

mit der Linkliste es funktioniert gut :)

0

Der folgende Code läuft für mich erfolgreich (so ziemlich das gleiche wie OPs Code, ersetzt nur undefinierte Symbole mit vernünftigen Alternativen):

import java.io.File; 
import java.io.StringWriter; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 

import javax.tools.JavaCompiler; 
import javax.tools.JavaFileObject; 
import javax.tools.ToolProvider; 

class CircularDeps { 
    public static void main(String[] args) throws Exception { 
    Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(
     new JavaSourceFromString(
      "A", 
      "package packageA; public class A { packageB.B b; }"), 
     new JavaSourceFromString(
      "B", 
      "package packageB; public class B { packageC.C c; }"), 
     new JavaSourceFromString(
      "C", 
      "package packageC; public class C { packageA.A a; }") 
     ); 

    JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
    if (jc == null) throw new Exception("Compiler unavailable"); 

    List<String> options = new ArrayList<>(); 
    options.add("-d"); 
    options.add(args[0]); 
    options.add("-classpath"); 

    URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
    StringBuilder sb = new StringBuilder(); 
    for (URL url : urlClassLoader.getURLs()) { 
      sb.append(url.getFile()).append(File.pathSeparator); 
    } 
    sb.append("output"); 
    options.add(sb.toString()); 

    StringWriter output = new StringWriter(); 
    boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
    if (success) { 
      System.out.println("Classes has been successfully compiled"); 
    } else { 
      throw new Exception("Compilation failed :" + output); 
    } 
    } 
} 

Ausgang:

Classes has been successfully compiled