Java 如何使用eclipse编译器进行独立的动态内存编译?

Java 如何使用eclipse编译器进行独立的动态内存编译?,java,eclipse,Java,Eclipse,eclipse编译器及其API与JDK中包含的编译器相比有一些显著的优势(对我的应用程序尤其有益),因此我想使用它。我有一个独立的实用程序,我想最小化它的大小和依赖性 访问eclipse编译器(最少的jar文件集和下载位置)并在内存中动态编译生成的代码的方法是什么?看起来您可以很容易地在中找到所需内容。通过单击最新版本下载ECJ,然后查找并下载文件ECJ-[version]罐子为此,我使用了4.2.1。在类路径中引用这个jar 您可以使用org.eclipse.jdt.internal.comp

eclipse编译器及其API与JDK中包含的编译器相比有一些显著的优势(对我的应用程序尤其有益),因此我想使用它。我有一个独立的实用程序,我想最小化它的大小和依赖性


访问eclipse编译器(最少的jar文件集和下载位置)并在内存中动态编译生成的代码的方法是什么?

看起来您可以很容易地在中找到所需内容。

通过单击最新版本下载ECJ,然后查找并下载文件ECJ-[version]罐子为此,我使用了4.2.1。在类路径中引用这个jar

您可以使用
org.eclipse.jdt.internal.compiler.compiler
。大多数构造函数都有可用的默认值。您只需以ICompilerRequestor的形式对结果进行回调。下面的示例使用一个简单的字节类加载器来测试结果。要进行级联编译,需要创建文件系统的子类,覆盖InameenEnvironment中的方法

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");
    }
}
package test.eclipse.compiler;
导入java.lang.reflect.Method;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.Map;
导入org.eclipse.jdt.internal.compiler.ClassFile;
导入org.eclipse.jdt.internal.compiler.CompilationResult;
导入org.eclipse.jdt.internal.compiler.compiler;
导入org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicys;
导入org.eclipse.jdt.internal.compiler.ICompilerRequestor;
导入org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
导入org.eclipse.jdt.internal.compiler.batch.FileSystem;
导入org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
导入org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
导入org.eclipse.jdt.internal.compiler.env.INameEnvironment;
导入org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
导入org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
导入org.eclipse.jdt.internal.compiler.util.util;
公共类TestCompile{
静态类字节类加载器扩展类加载器{
私有地图类地图;
公共字节类加载器(映射类映射){
超级();
this.classMap=classMap;
}
受保护类findClass(字符串名称)引发ClassNotFoundException{
byte[]bytes=classMap.get(名称);
如果(字节==null){
返回super.findClass(名称);
}否则{
返回defineClass(名称,字节,0,字节.长度);
}
}
}
公共静态void编译(字符串代码、字符串文件名){
ArrayList cp=新的ArrayList();
Util.collectRunningVMBootclasspath(cp);
INameEnvironment env=新名称env(cp.toArray(new FileSystem.Classpath[cp.size()]),null);
ICompilerRequestor requestor=新ICompilerRequestor(){
@凌驾
public void acceptResult(编译结果){
ClassFile[]cf=result.getClassFiles();
HashMap classMap=新的HashMap();
put(“Test”,cf[0].getBytes());
字节类加载器cl=新字节类加载器(类映射);
试一试{
c类=cl.loadClass(“试验”);
方法m=c.getMethod(“试验”);
m、 调用(空);
}捕获(例外e){
e、 printStackTrace();
}
}
};
编译器编译器=新编译器(env,defaultErrorHandlingPolicys.exitAfterAllProblems(),
新的编译器选项(),请求者,新的DefaultProblemFactory();
ICompilationUnit[]units=新的ICompilationUnit[]{new CompilationUnit(code.tocharray(),filename,null)};
编译(单位);
}
公共静态void main(字符串[]args){
编译(“公共类测试{public static void Test(){System.out.println(\'Hello,world.\”;}}”),
“Test.java”);
}
}

我不知道这是否是你想要的,但这是我在谷歌搜索“eclipse编译器”时得到的第一个点击:这正是我要说的,但请注意,不仅仅是编译器。谢谢!有没有什么地方告诉我们如何使用它来编译内存中的单个类?我将在问题中更清楚地指出这一点。我将把字符串写入一个以.java结尾的文件,并将其发送到ECJ.No。这是一个性能关键的情况。需要尽可能快。缺少NameEnv类。我发现了这个()但是它与应用程序的其他部分有很多依赖关系。你有没有一个简单的实现它的基本需要?