修改字节码工具javassist的使用小记

简介

Javassist是一个提供简单接口操作java字节码的工具。
它可以让你在一个已经编译好的类中添加新的方法,或者是修改已有的方法。
它不要求你对字节码方面具有多么深入的了解,同样的,它也允许你忽略被修改的类本身的细节和结构。

库的概要

主要的类

  • ClassPool
  • CtClass
  • CtMethod
  • CtField
    与和JDK反射API中java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method .Field相同类的操作。

主要的操作

  • CtClass.addMethod
  • CtClass.removeMethod
  • CtClass.removeField
  • CtClass.writeFile
  • CtClass.addField
  • CtMethod.insertBefore
  • CtMethod.insertAfter
  • CtMethod.insertAt
  • CtMethod.setBody

有这些操作就可完成对类的方法内部的修改

示例代码

演示了在指定类中
Main.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package wit.feng.javassist;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class Main {
public static void example() throws Exception {
CtClass cc = ClassPool.getDefault().get("wit.feng.javassist.ExampleClass");
CtMethod method = cc.getDeclaredMethod("sayhello");
method.insertBefore("System.out.println(\"before,\"+$1);");
ExampleClass obj = (ExampleClass) cc.toClass().newInstance();
obj.sayhello("world");
}

public static void main(String[] args) throws Exception {
example();
}
}

ExampleClass.java

1
2
3
4
5
6
7
8
9
package wit.feng.javassist;

public class ExampleClass {
public boolean sayhello(String msg)
{
System.out.println("hello,"+msg);
return true;
}
}

注意事项

  • 对类的方法进行修改时,引用方法的参数要用$1来代替
  • 对类的方法进行修改时,增加的代码好像不能引用原方法中的局部变量,写一样的变量名也不行
  • 对类的方法进行修改时,增加的代码的新增类,要写完整的类名,就算原来的类中有import。
  • 更高级的使用,见javassist的tutorial

参考

https://jboss-javassist.github.io/javassist/tutorial/tutorial.html
http://www.cnblogs.com/hucn/p/3636912.html
http://hao.jobbole.com/asm/
http://www.jianshu.com/p/43424242846b
http://www.blogjava.net/bukebushuo/articles/229703.html
http://blog.csdn.net/wzh695/article/details/2987474