javaassist修改constructor建構函式,增加方法,修改方法
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是在執行期前修改的位元組碼