转载

JAVA动态字节码

BCEL 可以深入 JVM 汇编语言进行类操作的细节。 BCEL 与 javassist 有不同的处理字节码方法, BCEL 在实际的 JVM 指令层次上进行操作,而 javassist 所强调的是源代码级别的工作。

ASM

是轻量级 java 字节码操作框架,直接涉及到 JVM 底层的操作和指令。 高性能,高质量

CGLB

基于 ASM 实现

javassist

性能低于 ASM 跟 CGLB 差不多,但是使用简单,很多开源框架都使用的是 javassist 。 javassist 比反射开销小,性能高。

javassist 的最外层的 API 和 JAVA 的反射包中的 API 颇为相似。它主要由 CtClass 、 CtMethod 以及 CtField 几个类组成,用以执行和 JDK 反射 API 中 java.lang.Class 、 java.lang.reflect.Method 、 java.lang.reflect.Field 相同的操作。

局限性

  1. JDK5.0 新语法不支持(包括泛型、枚举),不支持注解修改
  2. 不支持数组的初始化
  3. 不支持内部类和匿名类
  4. 不支持 continue 和 break 表达式
  5. 对于继承关系,有些不支持。

maven : mvnrepository.com/artifact/ja…

反射调用方法

public class User {

    private String name;
    private Integer age;


    public void sum(int a,int b){
        int sum = a + b;
        System.out.println("sum = " + sum);
    }


    public static void main(String[] args) {
        try {
            Class<?> clz = Class.forName("javassist.User");
            Object newInstance = clz.newInstance();
            Method method = clz.getDeclaredMethod("sum", int.class, int.class);
            Object invoke = method.invoke(newInstance, 1, 3);

        }catch (Exception e){

        }
    }
}
复制代码

javassist 生成 class 文件

//使用javassist创建class文件
 ClassPool pool = ClassPool.getDefault();
 //创建 class 文件
 CtClass userClass = pool.makeClass("com.beisiji.javassist.User");
 //创建 id 属性
 CtField idField = CtField.make("private Integer id;", userClass);
 //创建 name 属性
 CtField nameField = CtField.make("private String name;", userClass);
 //添加属性
 userClass.addField(idField);
 userClass.addField(nameField);
 //创建方法
 CtMethod setIdMethod = CtMethod.make("public void setId(Integer id) { this.id = id; }", userClass);
 CtMethod getIdMethod = CtMethod.make("public Integer getId() { return id; }", userClass);
 //添加方法
 userClass.addMethod(setIdMethod);
 userClass.addMethod(getIdMethod);

//创建构造器
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{CtClass.intType, pool.get("java.lang.String")}, userClass);
ctConstructor.setBody("{ this.id = id;this.name = name; }");
userClass.addConstructor(ctConstructor);
userClass.writeFile("C:/Users/yuanl/Desktop/md_dir");
复制代码

javassist 修改类文件信息

//使用javassist修改类文件信息(添加方法)
 ClassPool pool = ClassPool.getDefault();
 //需要加载的类信息(需要修改类信息的全限定名称)
 CtClass userClass = pool.get("executor.ExecutorDemo");
 //创建方法
 CtMethod method = new CtMethod(CtClass.intType, "add", new CtClass[]{CtClass.intType, CtClass.intType}, userClass);
 //设置方法权限
 method.setModifiers(Modifier.PUBLIC);
 method.setBody("{return $1 + $2;}");	//$0:this , $1第一个参数 , $2第二个参数
 userClass.addMethod(method);
 userClass.writeFile("C:/Users/yuanl/Desktop/md_dir");
 
 //调用添加的方法
 Class clz = userClass.toClass();
 Object newInstance = clz.newInstance();
 Method addMethod = clz.getDeclaredMethod("add", int.class, int.class);
 Object invoke = addMethod.invoke(newInstance, 2, 3);
 System.out.println("invoke = " + invoke);
复制代码
原文  https://juejin.im/post/5c693e16f265da2db1560939
正文到此结束
Loading...