转载

JAVA动态字节码

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

ASM

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

CGLB

基于 ASM 实现

javassist

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

javassist 的最外层的 APIJAVA 的反射包中的 API 颇为相似。它主要由 CtClassCtMethod 以及 CtField 几个类组成,用以执行和 JDK 反射 APIjava.lang.Classjava.lang.reflect.Methodjava.lang.reflect.Field 相同的操作。

局限性

  1. JDK5.0 新语法不支持(包括泛型、枚举),不支持注解修改
  2. 不支持数组的初始化
  3. 不支持内部类和匿名类
  4. 不支持 continuebreak 表达式
  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...