Java知识点总结(动态字节码操作-Javassist的API使用)

苏生

Java知识点总结(动态字节码操作-Javassist的API使用)

@(Java知识点总结)[Java, 动态字节码操作]

参考文章: 传送

操作示例:

public @interface Author {
  String name();
  int year();
}
@Author(name = "gs",year=2015)
public class Emp {
  private int num;
  private String name;
  
  public Emp() {
  }
  
  public Emp(int num, String name) {
   this();
   this.num = num;
   this.name = name;
  }
  
  public void sayHello(String name){
   System.out.print("你好,");
  }
  public int getNum() {
   return num;
  }
  public void setNum(int num) {
   this.num = num;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
  
}

 
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
 
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
 
/**
 * 测试 javassist 的 API
 *
 * @author Administrator
 *
 */
public class Test11 {
 
  // 通过类名加载已有的类
  public static void test1(ClassPool pool, CtClass cc) {
 
    try {
     cc = pool.get("com.gs.Emp");
 
     byte[] bytes = cc.toBytecode(); // 转化为字节码
     System.out.println(Arrays.toString(bytes));
 
     System.out.println(cc.getName()); // 获取类名
     System.out.println(cc.getSimpleName());
     System.out.println(cc.getSuperclass()); // 获取父类
     System.out.println(cc.getInterfaces()); // 获取接口
     
    } catch (Exception e) {
     e.printStackTrace();
    }
 
  }
 
  // 动态生成一个方法,并调用
  public static void test2(ClassPool pool, CtClass cc) {
 
    try {
     /*当CtClass对象通过writeFile()、toClass()、toBytecode()转化为Class后,
      * Javassist冻结了CtClass对象,因此,JVM不允许再次加载Class文件,所以不允许对其修改。
     因此,若想对CtClass对象进行修改,必须对其进行解冻,通过defrost()方法进行*/
     cc.defrost();
     // 生成一个方法
     CtMethod add = CtNewMethod.make("public int add(int a,int b){return $1+$2;}", cc);
     // 生成一个方法
     CtMethod subtraction = new CtMethod(CtClass.intType, "subtraction",
         new CtClass[] { CtClass.intType, CtClass.intType }, cc);
     subtraction.setModifiers(Modifier.PUBLIC);
     subtraction.setBody("return $1-$2;");
 
     cc.addMethod(add);
     cc.addMethod(subtraction);
 
     // 通过反射调用生成的方法
     Class clazz = cc.toClass();
     Emp emp = (Emp) clazz.newInstance();
     // Method method = clazz.getDeclaredMethod("add", new
     // Class[]{int.class,int.class});
     Method method = clazz.getDeclaredMethod("subtraction", new Class[] { int.class, int.class });
     Object result = method.invoke(emp, 200, 300);
     System.out.println(result);
    } catch (Exception e) {
    }
  }
 
  // 方法体前面和后面加执行语句
  public static void test3(ClassPool pool, CtClass cc) {
 
    try {
     cc.defrost();
     CtMethod m1 = cc.getDeclaredMethod("sayHello", new CtClass[] { pool.get("java.lang.String") });
     m1.insertBefore("System.out.println(\"方法体前面\");");
     m1.insertAfter("System.out.println($1);");
 
     // 通过反射调用生成的方法
     Class clazz = cc.toClass();
     Emp emp = (Emp) clazz.newInstance();
     Method method = clazz.getDeclaredMethod("sayHello", new Class[] { String.class });
     method.invoke(emp, "张三");
 
    } catch (Exception e) {
     e.printStackTrace();
    }
 
  }
 
  // 生成属性和方法
  public static void test4(ClassPool pool, CtClass cc) {
    try {
     // CtField.make("private double salary;", cc);
     CtField field = new CtField(CtClass.doubleType, "salary", cc);
     field.setModifiers(Modifier.PRIVATE);
     cc.addField(field);
 
     // cc.getDeclaredField("salary"); //获取属性
 
     CtMethod method = CtNewMethod.getter("getSalary", field);
     cc.addMethod(method);
 
     CtMethod method2 = CtNewMethod.getter("setSalary", field);
     cc.addMethod(method2);
    } catch (Exception e) {
     e.printStackTrace();
    }
 
  }
 
  // 生成构造器
  public static void test5(ClassPool pool, CtClass cc) {
 
    try {
     cc.defrost();
     CtConstructor[] cs = cc.getConstructors();
     for (CtConstructor c : cs) {
       System.out.println(c.getLongName());
       c.insertAfter("System.out.println(\"可以在构造器前后加代码\");");
     }
    } catch (Exception e) {
     e.printStackTrace();
    }
 
  }
 
  // 注解操作
  public static void test6(ClassPool pool, CtClass cc) {
    try {
     cc.defrost();
     Object[] annotations = cc.getAnnotations();
     Author author = (Author) annotations[0];
     System.out.println("name:" + author.name() + ",year:" + author.year());
 
    } catch (Exception e) {
     e.printStackTrace();
    }
  }
 
  public static void main(String[] args) {
    ClassPool pool = ClassPool.getDefault();
    CtClass cc = null;
    try {
     cc = pool.get("com.gs.Emp");
    } catch (NotFoundException e) {
     e.printStackTrace();
    }
 
    test1(pool, cc);
    //test2(pool, cc);
    test3(pool, cc);
    test5(pool, cc);
    test6(pool, cc);
  }
}
阅读 1.3k

Java笔记
Java知识点总结
652 声望
27 粉丝
0 条评论
652 声望
27 粉丝
宣传栏