Java bytecode engineering toolkit since 1999

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由日本的 Shigeru Chiba 所创建的,它已加入了开放源代码 JBoss 应用服务器项目,通过使用 Javassist 对字节码操作为 JBoss 实现动态"AOP"框架。

关于java字节码的处理,目前有很多工具,如bcel,ASM。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点在于简单、快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
Javassist (Java Programming Assistant) makes Java bytecode manipulation simple. It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it.
Javassist(Java Programming Assistant)使Java字节码操作变得简单。它是一个用于在Java中编辑字节码的类库;它使Java程序能够在运行时定义新类,并在JVM加载时修改类文件。
1.javassist 获取类的基本信息

ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.get("org.example.domain.Student");
        //得到字节码
        byte[] bytes = ctClass.toBytecode();
        //获取长度
        System.out.println(bytes.length);
        //获取类名
        System.out.println(ctClass.getName());
        //获取简要类名
        System.out.println(ctClass.getSimpleName());
        //获取父类
        System.out.println(ctClass.getSuperclass().getName());
        //获取接口
        System.out.println(Arrays.toString(ctClass.getInterfaces()));
        //获取构造方法
        for(CtConstructor ctConstructor : ctClass.getConstructors()){
            System.out.println("构造方法 "+ctConstructor.getName());
        }
        //获取方法
        for(CtMethod ctMethod : ctClass.getMethods()){
            System.out.println("所有方法:"+ctMethod.getName());
        }

        for(CtMethod ctMethod : ctClass.getDeclaredMethods()){
            System.out.println("定义方法:"+ctMethod.getName());
        }

        for(CtField ctField : ctClass.getDeclaredFields()){
            System.out.println("定义属性:"+ctField.getName());
            System.out.println("属性类型:"+ctField.getType());
        }

2.在原有的方法后面添加自己定义的

ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.get("org.example.domain.Student");
        CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
        ctMethod.insertBefore("System.out.println(\"调用前1\");");
        ctMethod.insertAt(20094, "System.out.println(\"在指定行插入代码\");");//貌似行号胡乱写也可以
        ctMethod.insertAfter("{" + "System.out.println(\"你好:\" + this.getName()+\",今年:\"+this.getAge());" + "}");
        Class newClass = ctClass.toClass();
        Student student = (Student) newClass.newInstance();
        student.setName("张三");
        student.setAge(18);
        student.sayHello();

注意,如果使用 JDK9 以下的JDK ,同时使用 3.20.0-GA 以上版本的 Javassist,调用 toClass 方法会报 StackWalker 异常
3.javassist 在声明的方法中重新定义内容

ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.get("org.example.domain.Student");
        CtMethod ctMethod = ctClass.getDeclaredMethod("hello",new CtClass[]{classPool.get("java.lang.String")});
        ctMethod.setBody("{" + "System.out.println(\"你好:\" + $1);" + "}");
        //ctClass.writeFile("C:\\installsoft\\");
        //加载修改后的类,注意:必须保证调用前此类未加载
        ctClass.toClass();
        new Student().hello("包青天");```
4.javassist 创建类 属性 方法 构造器 注解

ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass(“org.example.domain.User”);

   //创建属性
    ctClass.addField(CtField.make("private int id;",ctClass));
    ctClass.addField(CtField.make("private String name;",ctClass));

    CtField ctField = new CtField(CtClass.intType,"age",ctClass);
    ctField.setModifiers(Modifier.PRIVATE);
    ctClass.addField(ctField);
    ctClass.addMethod(CtNewMethod.getter("getAge",ctField));
    ctClass.addMethod(CtNewMethod.setter("setAge",ctField));



    //创建方法
    ctClass.addMethod(CtMethod.make("public String getName(){return name;}",ctClass));
    ctClass.addMethod(CtMethod.make("public void setName(String name){this.name=name;}",ctClass));

    //创建方法
    CtClass[] ctClasses = new CtClass[]{CtClass.intType};
    // 返回值,方法名,参数,对象
    CtMethod ctMethod = new CtMethod(CtClass.intType,"setId",ctClasses,ctClass);
    //访问范围
    ctMethod.setModifiers(Modifier.PUBLIC);
    //方法体
    ctMethod.setBody("{return  $1;}");
    ctClass.addMethod(ctMethod);

    //添加注解
    ClassFile classFile = ctClass.getClassFile();
    ConstPool constPool = classFile.getConstPool();

    AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
    //创建要添加的注解
    Annotation annotation = new Annotation(SerializedName.class.getCanonicalName(),constPool);
    //设置注解中的属性和值
    annotation.addMemberValue("value",new StringMemberValue("p",constPool));
    //把这个注解添加到AnnotationsAttribute对象里面
    annotationsAttribute.addAnnotation(annotation);
    //把这个对象放到要打上注解的字段/类上
    ctField.getFieldInfo().addAttribute(annotationsAttribute);
    //添加构造器
    CtConstructor ctConstructor = new CtConstructor(new CtClass[]{ CtClass.intType,classPool.get("java.lang.String")},ctClass);
    ctConstructor.setBody("{this.id = id;this.name = name;}");
    ctClass.addConstructor(ctConstructor);

    ctClass.writeFile("C:\\installsoft\\springbootdisruptor\\src\\main\\java");

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐