2013-01-09 7 views
6

Il compilatore di eclipse e la relativa API presentano alcuni vantaggi significativi (particolarmente vantaggiosi per la mia applicazione) rispetto a quelli inclusi nel JDK e quindi mi piacerebbe utilizzarlo. Ho una utility standalone e voglio ridurne le dimensioni e le dipendenze.Come eseguire la compilazione in memoria autonoma con il compilatore eclipse?

Qual è il modo per accedere al compilatore di eclipse (set minimo di file jar e dove scaricarli) e compilare il codice generato al volo nella memoria?

+0

Non so se questo è quello che stai cercando, ma è stato il primo colpo che ho ricevuto da googling "eclisse compilatore": http: // www. eclipse.org/jdt/core/index.php –

+0

Questo è un po 'quello di cui sto parlando, ma si noti che è molto più di un semplice compilatore. – mentics

risposta

4

Scarica la ECJ di starting from this page, facendo clic sull'ultima versione, quindi trova e scarica il file ecj- [versione] .jar. Per questo, sto usando 4.2.1. Fai riferimento a questo jar nel tuo classpath.

Si utilizza org.eclipse.jdt.internal.compiler.Compiler. La maggior parte delle cose per il costruttore sono disponibili i valori predefiniti. Basta dare un callback per i risultati sotto forma di un ICompilerRequestor. L'esempio seguente utilizza un semplice programma di caricamento classe byte per testare i risultati. Per eseguire la compilazione a cascata, creare una sottoclasse di FileSystem, sovrascrivendo i metodi da INameEnvironment.

package test.eclipse.compiler; 

import java.lang.reflect.Method; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

import org.eclipse.jdt.internal.compiler.ClassFile; 
import org.eclipse.jdt.internal.compiler.CompilationResult; 
import org.eclipse.jdt.internal.compiler.Compiler; 
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; 
import org.eclipse.jdt.internal.compiler.ICompilerRequestor; 
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; 
import org.eclipse.jdt.internal.compiler.batch.FileSystem; 
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; 
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 
import org.eclipse.jdt.internal.compiler.env.INameEnvironment; 
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 
import org.eclipse.jdt.internal.compiler.util.Util; 


public class TestCompile { 
    static class ByteClassLoader extends ClassLoader { 
     private Map<String, byte[]> classMap; 


     public ByteClassLoader(Map<String, byte[]> classMap) { 
      super(); 
      this.classMap = classMap; 
     } 

     protected Class<?> findClass(String name) throws ClassNotFoundException { 
      byte[] bytes = classMap.get(name); 
      if (bytes == null) { 
       return super.findClass(name); 
      } else { 
       return defineClass(name, bytes, 0, bytes.length); 
      } 
     } 
    } 


    public static void compile(String code, String filename) { 
     ArrayList<Classpath> cp = new ArrayList<FileSystem.Classpath>(); 
     Util.collectRunningVMBootclasspath(cp); 
     INameEnvironment env = new NameEnv(cp.toArray(new FileSystem.Classpath[cp.size()]), null); 
     ICompilerRequestor requestor = new ICompilerRequestor() { 
      @Override 
      public void acceptResult(CompilationResult result) { 
       ClassFile[] cf = result.getClassFiles(); 
       HashMap<String, byte[]> classMap = new HashMap<String, byte[]>(); 
       classMap.put("Test", cf[0].getBytes()); 
       ByteClassLoader cl = new ByteClassLoader(classMap); 
       try { 
        Class<?> c = cl.loadClass("Test"); 
        Method m = c.getMethod("test"); 
        m.invoke(null); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }; 
     Compiler compiler = new Compiler(env, DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
       new CompilerOptions(), requestor, new DefaultProblemFactory()); 

     ICompilationUnit[] units = new ICompilationUnit[] { new CompilationUnit(code.toCharArray(), filename, null) }; 
     compiler.compile(units); 
    } 

    public static void main(String[] args) { 
     compile("public class Test { public static void test() { System.out.println(\"Hello, world.\"); }}", 
       "Test.java"); 
    } 
} 

copiato con il permesso di this blog post

1

Sembra che tu possa trovare quello che stai cercando in the maven repository e use it con ant abbastanza facilmente.

+0

Grazie! C'è qualche parte che dice come usarlo per compilare una singola classe in memoria? Lo indicherò più chiaramente nella domanda. – mentics

+0

Scriverei la stringa in un file che termina con .java e inviarlo a ECJ. – hd1

+0

No. Questa è una situazione critica per le prestazioni. Ha bisogno di essere il più veloce possibile. – mentics

Problemi correlati