7

Eclipse コンパイラーとその API には、JDK に含まれているものよりもいくつかの重要な利点 (特に私のアプリケーションにとって有益) があるので、それを使用したいと思います。スタンドアロン ユーティリティがあり、そのサイズと依存関係を最小限に抑えたいと考えています。

eclipse コンパイラ (jar ファイルの最小セットとそれらをダウンロードする場所) にアクセスし、生成されたコードをオンザフライでメモリにコンパイルする方法は何ですか?

4

2 に答える 2

5

このページから始めて、最新リリースをクリックしてECJをダウンロードし、ecj-[バージョン].jar ファイルを見つけてダウンロードします。このために、私は 4.2.1 を使用しています。クラスパスでこの jar を参照します。

を使用しorg.eclipse.jdt.internal.compiler.Compilerます。コンストラクターのほとんどのものには、使用可能なデフォルトがあります。ICompilerRequestor の形式で結果のコールバックを渡すだけです。以下の例では、単純なバイト クラス ローダーを使用して結果をテストしています。カスケード コンパイルを行うには、FileSystem のサブクラスを作成し、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");
    }
}

このブログ投稿から許可を得てコピー

于 2013-01-09T21:55:03.973 に答える
1

Maven リポジトリで探しているものを見つけて、antで簡単に使用できるようです。

于 2013-01-09T01:04:54.520 に答える