如何使用javassist编译源代码?

时间:2014-09-30 09:21:09

标签: java compilation javassist

我有一个String

public class Hesey {
    public void testAdd() {
        System.out.println("Hi");
    }
}

我是否可以使用一部分API来编译此StringClass并加载此类' Class&#39 ;?或者我是否必须使用ToolProvider.getSystemJavaCompiler()来编译整个源?

2 个答案:

答案 0 :(得分:1)

看看OpenHFT Java Runtime Compiler

它支持将动态提供的Java源代码编译为字符串:

private final CachedCompiler cc = new CachedCompiler(null, null);

Class aClass = cc.loadFromJava(className, javaCode);
Object o = aClass.newInstance();  // instance of the object declared in 'javaCode'

其中javaCode是Java源代码的字符串表示形式。在幕后,我相信它正在使用ToolProvider.getSystemJavaCompiler()。

答案 1 :(得分:1)

  1. AFAIK,Javassist不允许我们从文本中构建一个类。以下是我用于使用该库构建类的代码:

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import javassist.CannotCompileException;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtField;
    import javassist.CtMethod;
    import javassist.NotFoundException;
    
    public class CtClassTemplate {
    
        public static volatile String                   CLASS_DEBUG_PATH = null;
    
        private final String                            name;
        private String                                  extendsClass;
        private final List<String>                      implementsInterfaces = new ArrayList<>();
        private final List<CtFieldTemplate>             fields = new ArrayList<>();
        private final List<CtMethodTemplate>            methods = new ArrayList<>();
    
        public CtClassTemplate(final String name) {
            this.name = name;
        }
    
        public void setExtends(final String className) {
            this.extendsClass = className;
        }
    
        public void addImplements(final String ifcName) {
            implementsInterfaces.add(ifcName);
        }
    
        public CtFieldTemplate addField(final String code) {
            final CtFieldTemplate result = new CtFieldTemplate(code);
            fields.add(result);
            return result;
        }
    
        public CtMethodTemplate addMethod(final String code) {
            final CtMethodTemplate result = new CtMethodTemplate(code);
            methods.add(result);
            return result;
        }
    
        public <T extends Class> T createClass(final ClassPool pool) throws CannotCompileException {
            return createClass(pool, CtClassTemplate.class.getClassLoader());
        }
    
        public <T extends Class> T createClass(final ClassPool pool, final ClassLoader cl) throws CannotCompileException {
            try {
    
                final CtClass ctClass = pool.makeClass(name);
    
                if (extendsClass != null && !extendsClass.isEmpty()) {
                    ctClass.setSuperclass(pool.get(extendsClass));
                }
    
                for (String ifc : implementsInterfaces) {
                    ctClass.addInterface(pool.get(ifc));
                }
    
                for (CtFieldTemplate field : fields) {
                    final CtField ctField = CtField.make(field.getCode(), ctClass);
                    ctClass.addField(ctField);
                }
    
                for (CtMethodTemplate method : methods) {
                    final CtMethod ctMethod = CtMethod.make(method.getCode(), ctClass);
                    ctClass.addMethod(ctMethod);
                }
    
                final String cdp = CLASS_DEBUG_PATH;
    
                if (cdp != null) {
                    ctClass.writeFile(cdp);
                }
    
                return (T) ctClass.toClass(cl, null);
    
            } catch (NotFoundException | IOException e) {
                throw new CannotCompileException(e);
            }      
        }
    
        public class CtMethodTemplate {
            private String code;
    
            private CtMethodTemplate(String code) {
                this.code = code;
            }    
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }                        
        }
    
        public class CtFieldTemplate {
            private String code;
    
            private CtFieldTemplate(String code) {
                this.code = code;
            }    
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }                        
        }
    
    }
    
  2. 你可以像这样使用它:

        final ClassPool ctPool = new ClassPool(true);
    
        final CtClassTemplate aTmpl = new CtClassTemplate("foopackage.A");
        aTmpl.setExtends("foopackage.B");
        aTmpl.addImplements("foopackage.CIfc");
        aTmpl.addImplements("foopackage.onemorefoopackage.DIfc");
        aTmpl.addField("private int i;");
        aTmpl.addMethod("public int getI() { return i; }");
        aTmpl.addMethod("public void setI(int i) { this.i = $1; }");
    
        final Class aClass = aTmpl.createClass(ctPool);
    

    或者在你的情况下:

        final CtClassTemplate aTmpl = new CtClassTemplate("Hesey");
        aTmpl.addMethod("public void testAdd() { System.out.println(\"Hi\"); }");
    
        final Class aClass = aTmpl.createClass(ctPool);
    

    不幸的是,并非真正的整篇文章,但主要是:)

    1. 使用ToolProvider.getSystemJavaCompiler()也看起来不错(OpenHFT Java Runtime Compiler是一个很好的包装器),但是您需要使用JDK来运行您的应用程序或运送&#34; tools.jar&#34;至少。这可能不方便。