前言
Java 字节码以二进制的形式存储在 class 文件中,每一个 class 文件包含一个 Java 类或接口。
Javaassist 就是一个用来处理 Java 字节码的类库
Javassist是一个开源的分析、编辑和创建Java字节码的类库,可以直接编辑和生成Java生成的字节码。相对于bcel, asm等这些工具,开发者不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。javassist简单易用, 快速。javassist是jboss的一个子项目。
重要的类
接下来来介绍类库里几个比较重要的类
ClassPool:
javassist的类池,使用ClassPool 类可以跟踪和控制所操作的类,它的工作方式与 JVM 类装载器非常相似
CtClass
CtClass表示类,一个CtClass(编译时类)对象可以处理一个class文件
CtMethod
表示类的方法
ClassClassPath
用于获取类文件的搜索路径。
CtFields
表示类的字段
代码实例
首先构造两段代码,
public class persion {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) { this.age = age;
}
public String getName() { return name;
}
public void setName(String name) { this.name = name;
}
public void sayHello(){
System.out.println("Hello, My name is " + this.name);
}
}
public class main {
public static void main(String[]args) {
persion persion =new persion();
persion.setName("ice");
persion.sayHello();
}
}
toclass
import javassist.*;
public class main {
public static void main(String[]args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException {
ClassPool pool = ClassPool.getDefault();//加载类池库,默认获取所有JVM
CtClass ctClass = pool.get("persion"); //从类池库里获取persion类
CtMethod ctMethod=ctClass.getDeclaredMethod("sayHello");//获取sayHello方法
//插入这么一段代码
ctMethod.insertAfter("System.out.println(\" this is add ===I'm \" + this.age + \" years old.\");");
//再转为class
Class<?> newa = ctClass.toClass();
//实例化
persion persion = (persion) newa.newInstance();
persion.setName("ice");
persion.getAge(11);
persion.sayHello();
}
}
tobyte
import javassist.*;
import java.io.IOException;
import java.util.Arrays;
public class main {
public static void main(String[]args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException, IOException {
ClassPool pool = ClassPool.getDefault();//加载类池库,默认获取所有JVM
CtClass ctClass = pool.get("persion"); //从类池库里获取persion类
CtMethod ctMethod=ctClass.getDeclaredMethod("sayHello");//获取sayHello方法
//插入这么一段代码
ctMethod.insertBefore("System.out.println(\" this is add ===I'm \" + this.age + \" years old.\");");
//再转为class
byte[] newa = ctClass.toBytecode();
//实例化
String s = Arrays.toString(newa);
System.out.println(s);
}
}
我们在上述代码中添加了一个println,并且成功对其进行TolClass操作和ToBytes操作,这也就意味着class和bytes是可以互相转化的。
总结
javassist就是能在代码写的类之后,利用直接编辑所生成的字节码,从而产生一个“新”的类。
因此javassist也常用于动态代理功能。