前言
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
表示类的字段

代码实例

首先构造两段代码,

  1. public class persion {
  2. private int age;
  3. private String name;
  4. public int getAge() {
  5. return age;
  6. }
  7. public void setAge(int age) { this.age = age;
  8. }
  9. public String getName() { return name;
  10. }
  11. public void setName(String name) { this.name = name;
  12. }
  13. public void sayHello(){
  14. System.out.println("Hello, My name is " + this.name);
  15. }
  16. }
  1. public class main {
  2. public static void main(String[]args) {
  3. persion persion =new persion();
  4. persion.setName("ice");
  5. persion.sayHello();
  6. }
  7. }

按照上面的输出,ok没什么问题

image.png

toclass

  1. import javassist.*;
  2. public class main {
  3. public static void main(String[]args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException {
  4. ClassPool pool = ClassPool.getDefault();//加载类池库,默认获取所有JVM
  5. CtClass ctClass = pool.get("persion"); //从类池库里获取persion类
  6. CtMethod ctMethod=ctClass.getDeclaredMethod("sayHello");//获取sayHello方法
  7. //插入这么一段代码
  8. ctMethod.insertAfter("System.out.println(\" this is add ===I'm \" + this.age + \" years old.\");");
  9. //再转为class
  10. Class<?> newa = ctClass.toClass();
  11. //实例化
  12. persion persion = (persion) newa.newInstance();
  13. persion.setName("ice");
  14. persion.getAge(11);
  15. persion.sayHello();
  16. }
  17. }

可以看到通过javassist加载了一段代码进入类中
image.png

tobyte

  1. import javassist.*;
  2. import java.io.IOException;
  3. import java.util.Arrays;
  4. public class main {
  5. public static void main(String[]args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException, IOException {
  6. ClassPool pool = ClassPool.getDefault();//加载类池库,默认获取所有JVM
  7. CtClass ctClass = pool.get("persion"); //从类池库里获取persion类
  8. CtMethod ctMethod=ctClass.getDeclaredMethod("sayHello");//获取sayHello方法
  9. //插入这么一段代码
  10. ctMethod.insertBefore("System.out.println(\" this is add ===I'm \" + this.age + \" years old.\");");
  11. //再转为class
  12. byte[] newa = ctClass.toBytecode();
  13. //实例化
  14. String s = Arrays.toString(newa);
  15. System.out.println(s);
  16. }
  17. }

image.png
我们在上述代码中添加了一个println,并且成功对其进行TolClass操作和ToBytes操作,这也就意味着class和bytes是可以互相转化的。

总结

javassist就是能在代码写的类之后,利用直接编辑所生成的字节码,从而产生一个“新”的类。
因此javassist也常用于动态代理功能。