2012-04-12 6 views
0

Ich folge dem Tutorial von Generating Java classes dynamically through Java compiler API, der Code ist Arbeit, aber was ich sehe, ist das Programm wird eine Klassendatei nach dem Kompilieren erstellen.Dynamisches Kompilieren ohne Erstellen einer physischen Datei

import java.io.IOException; 
import java.net.URI; 
import java.util.Arrays; 
import java.util.Locale; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.tools.JavaCompiler.CompilationTask; 
import javax.tools.*; 

public class Compiler { 

    static final Logger logger = Logger.getLogger(Compiler.class.getName()); 
    static String sourceCode = "class HelloWorld{" 
     + "public static void main (String args[]){" 
     + "System.out.println (\"Hello, dynamic compilation world!\");" 
     + "}" 
     + "}"; 

    public void doCompilation() { 

     SimpleJavaFileObject fileObject = new DynamicJavaSourceCodeObject("HelloWorld", sourceCode); 
     JavaFileObject javaFileObjects[] = new JavaFileObject[]{fileObject}; 

     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

     StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null); 

     Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObjects); 

     DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); 

     CompilationTask compilerTask = compiler.getTask(null, stdFileManager, diagnostics, null, null, compilationUnits); 

     boolean status = compilerTask.call(); 

     if (!status) { 
      for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { 
       System.out.format("Error on line %d in %s\n", diagnostic.getLineNumber(), diagnostic); 
      } 
     } 
     try { 
      stdFileManager.close(); 
     } catch (IOException ex) { 
      Logger.getLogger(Compiler.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public static void main(String args[]) { 
     new Compiler().doCompilation(); 
    } 
} 

class DynamicJavaSourceCodeObject extends SimpleJavaFileObject { 

    private String qualifiedName; 
    private String sourceCode; 

    protected DynamicJavaSourceCodeObject(String name, String code) { 
     super(URI.create("string:///" + name.replaceAll("\\.", "/") + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE); 
     this.qualifiedName = name; 
     this.sourceCode = code; 
    } 

    @Override 
    public CharSequence getCharContent(boolean ignoreEncodingErrors) 
     throws IOException { 
     return sourceCode; 
    } 

    public String getQualifiedName() { 
     return qualifiedName; 
    } 

    public void setQualifiedName(String qualifiedName) { 
     this.qualifiedName = qualifiedName; 
    } 

    public String getSourceCode() { 
     return sourceCode; 
    } 

    public void setSourceCode(String sourceCode) { 
     this.sourceCode = sourceCode; 
    } 
} 

Ist es möglich, dass compilerTask.call(); nach Aufruf nicht eine Klassendatei zu erstellen? Wenn ja, wie?

+0

Bezieht sich auf: http://stackoverflow.com/questions/616532/on-the-fly-in-memory -java-code-compilation-for-java-5-and-java-6 –

+0

Mögliches Duplikat von [Wie kompilieren und laden Sie externe Java-Klassen dynamisch?] (https://stackoverflow.com/questions/21544446/how- do-you-dynamic-compile-and-load-external-Java-Klassen) – ldmtwo

Antwort

4

Für was Sie tun, würde ich Janino verwenden. Es scheint nur mit der JavaCompiler machbar, aber nicht gut dokumentiert. Siehe den Kommentar, den ich mit der verknüpften Frage hinzugefügt habe, um ein Beispiel dafür zu geben, wie man mit dem JavaCompiler vorgeht.

EDIT: Ich fand eine example mit der JavaCompiler einfach zu verstehen. "-proc: nur"

+0

Die Tutorials funktioniert, danke ... – Crazenezz

0

Um das Argument Erstellung von Klassendatei durch die JavaCompiler verwenden zu vermeiden