使用javassist修改类时出错

时间:2017-09-21 08:56:43

标签: java constructor bytecode javassist

我正在使用javassist 3.19.0-GA jar文件用java代码修改构造函数体。这是我的代码

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.19.0-GA</version>
</dependency>

和java文件

package org.springframework.aop.framework;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.LoaderClassPath;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class JavassistApplication extends XmlWebApplicationContext {

    static {
        ClassPool classPool = ClassPool.getDefault();
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            classPool.appendClassPath(new LoaderClassPath(classLoader));
            CtClass cc = classPool.get("org.springframework.aop.framework.ProxyCreatorSupport");
            /*modify the constructor body with java code*/
            CtConstructor c = cc.getConstructors()[0];
            c.insertAfter("$0.aopProxyFactory = new org.springframework.aop.framework.JavassistAopProxyFactory();");
             /*Here getting exceptions when i run*/
            cc.toClass();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}

和JavassistAopProxyFactory()的代码:

package org.springframework.aop.framework;
import org.springframework.aop.SpringProxy;
import org.springframework.util.ClassUtils;
import java.io.Serializable;

public class JavassistAopProxyFactory implements AopProxyFactory, Serializable {

    private static final long serialVersionUID = -37444691555886L;
    // Whether the Javassist library is present on the classpath
    private static final boolean javassistAvailable =
            ClassUtils.isPresent("javassist.ClassPool", JavassistAopProxyFactory.class.getClassLoader());


    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }
            if (!javassistAvailable) {
                throw new AopConfigException(
                        "Cannot proxy target class because Javassist is not available. " +
                                "Add Javassist to the class path or specify proxy interfaces.");
            }
            return new JavassistAopProxy(config);
        } else {
            return new JdkDynamicAopProxy(config);
        }
    }

    /**
     * Determine whether the supplied {@link AdvisedSupport} has only the
     * {@link org.springframework.aop.SpringProxy} interface specified
     * (or no proxy interfaces specified at all).
     */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class[] interfaces = config.getProxiedInterfaces();
        return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0])));
    }

}

我的错误是

 java.lang.IllegalStateException: javassist.CannotCompileException: by java.lang.LinkageError: org.springframework.aop.framework.ProxyCreatorSupport
at org.springframework.aop.framework.JavassistApplicationContext.<clinit>

我尝试添加cc.defrost();cc.writeFile();。我不知道为什么会出现这种异常。这是JavassistAopProxyFactory类的新方法中的一个问题吗?

c.insertAfter("$0.aopProxyFactory = new org.springframework.aop.framework.JavassistAopProxyFactory();"); 

classpool.class文件中,我可以看到代码

 public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain)
/*      */     throws CannotCompileException
/*      */   {
/*      */     try
/*      */     {
/* 1065 */       byte[] b = ct.toBytecode();
/*      */       Object[] args;
/*      */       Method method;
/* 1068 */       Object[] args; if (domain == null) {
/* 1069 */         Method method = defineClass1;
/* 1070 */         args = new Object[] { ct.getName(), b, new Integer(0), new Integer(b.length) };
/*      */       }
/*      */       else
/*      */       {
/* 1074 */         method = defineClass2;
/* 1075 */         args = new Object[] { ct.getName(), b, new Integer(0), new Integer(b.length), domain };
/*      */       }
/*      */       
/*      */ 
/* 1079 */       return toClass2(method, loader, args);
/*      */     }
/*      */     catch (RuntimeException e) {
/* 1082 */       throw e;
/*      */     }
/*      */     catch (InvocationTargetException e) {
/* 1085 */       throw new CannotCompileException(e.getTargetException());
/*      */     }
/*      */     catch (Exception e) {
/* 1088 */       throw new CannotCompileException(e);
/*      */     }
/*      */   }
/*      */  

我在行号1085上遇到异常。

我已经从Use javassist to modify fields that use getters and setters in a class constructorjava javassist.CannotCompileException: by java.lang.LinkageError: loader研究了一些类似的问题。但仍然遇到同样的问题。任何解决方案?

1 个答案:

答案 0 :(得分:0)

我会尝试更改调用并使用内部setter设置工厂:

package org.springframework.aop.framework;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.LoaderClassPath;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class JavassistApplication extends XmlWebApplicationContext {

    public JavassistApplication(){
        ClassPool classPool = ClassPool.getDefault();
        try {
            // ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            // classPool.appendClassPath(new LoaderClassPath(classLoader));
            CtClass cc = classPool.get("org.springframework.aop.framework.ProxyCreatorSupport");
            /*modify the constructor body with java code*/
            CtConstructor c = cc.getConstructors()[0];
            c.insertAfter("setAopProxyFactory(new org.springframework.aop.framework.JavassistAopProxyFactory());");
             /*Here getting exceptions when i run*/
            cc.toClass();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}