javaassist修改constructor构造函数,增加方法,修改方法

public class SimplePrincipal implements Principal, Serializable
   35   {
   36      private static final long serialVersionUID = 7701951188631723261L;
   37      private final String name;
   38   
   39      public SimplePrincipal(String name)
   40      {
   41         this.name = name;

   42      }

ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("org.jboss.security.SimplePrincipal");
CtConstructor ctc = cc.getConstructors()[0];
ctc.setBody("{name=\"modify name\";this.name = name;}");
SimplePrincipal sp=(SimplePrincipal)cc.toClass().getConstructor(String.class).newInstance("name");

System.out.println(sp.getName());

SimplePrincipal pp=new SimplePrincipal("ww");
System.out.println(pp.getName());

输出

modify name

modify name


应该是整个classloader的simpleprincipal都被改了

为了保证只有当前的SimplePrincipal被修改

ClassPool cp = ClassPool.getDefault();
CtMethod m=CtNewMethod.make("public void modifyName(String name);", cc);CtClass cc = cp.get("org.jboss.security.SimplePrincipal");
CtMethod m=CtNewMethod.make("public void modifyName(String name);", cc);

m.setBody("{this.name= $1;}");  
cc.addMethod(m);
Object sp=cc.toClass().getConstructor(String.class).newInstance("name");

Method mm=sp.getClass().getDeclaredMethod("modifyName",String.class);
mm.invoke(sp, "hello");
System.out.println(((SimplePrincipal)sp).getName());

SimplePrincipal pp=new SimplePrincipal("ww");
System.out.println(pp.getName());

这里的setBody中的$1是指第一个参数(javaassist的规则)

输出

hello

ww

如果想修改己有方法的内容

CtMethod cm = ... ;
cm.instrument(
    new ExprEditor() {
        public void edit(MethodCall m)
                      throws CannotCompileException
        {
            if (m.getClassName().equals("Point")
                          && m.getMethodName().equals("move"))
                m.replace("{ $1 = 0; $_ = $proceed($$); }");
        }
    });

exprEditor没有细细研究,以后有机会研究再更新吧

attempted  duplicate class definition for name

这个错误是因为同一个classloader加载了两次SimplePrincipal

因为javaassist是在运行期前修改的字节码


你可能感兴趣的:(jvm)