Java字节码操作(JAVAassist)

在这里插入图片描述

常见的字节码操作类库

在这里插入图片描述
https://github.com/jboss-javassist/javassist

JAVAssist的API详解

在这里插入图片描述
Intellij IDEA 添加jar包的三种方式

用javassist生成一个新的类

import javassist.*;

/**
 * 测试用javassist生成一个新的类
 */
public class Demo01 {
    
    

    public static void main(String[] args) throws Exception{
    
    

        // 获取类池
        ClassPool pool = ClassPool.getDefault();

        // 创建新类
        CtClass cc = pool.makeClass("test.bean.Emp");

        // 创建属性
        CtField f1 = CtField.make("private int empno;", cc);
        CtField f2 = CtField.make("private String ename;", cc);
        cc.addField(f1);
        cc.addField(f2);

        // 创建方法
        CtMethod m1 = CtMethod.make("public int getEmpno(){return empno;}", cc);
        CtMethod m2 = CtMethod.make("public void setEmpno(int empno){this.empno = empno;}", cc);
        cc.addMethod(m1);
        cc.addMethod(m2);

        // 添加构造器
        CtConstructor constructor = new CtConstructor(new CtClass[]{
    
    CtClass.intType, pool.get("java.lang.String")}, cc);
        constructor.setBody("{this.empno=empno; this.ename=ename;}");
        cc.addConstructor(constructor);

        cc.writeFile("./");  // 将上面创建好的类写入指定文件夹下
        System.out.println("Successful !!!");
    }
}

生成.class文件

XJad反编译工具

找到字节码所在目录打开即可
在这里插入图片描述

在这里插入图片描述

JAVAssist库的API详解

在这里插入图片描述
test.Emp

package test;

public class Emp {
    
    
    private int empno;
    private String ename;

    public void sayHello(int a){
    
    
        System.out.println("sayHello " + a);
    }

    public int getEmpno() {
    
    
        return empno;
    }

    public void setEmpno(int empno) {
    
    
        this.empno = empno;
    }

    public String getEname() {
    
    
        return ename;
    }

    public void setEname(String ename) {
    
    
        this.ename = ename;
    }

    public Emp(int empno, String ename) {
    
    
        this.empno = empno;
        this.ename = ename;
    }

    public Emp(){
    
    

    }
}

Demo

package test;

import javassist.*;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 测试用javassist API
 */
public class Demo02 {
    
    

    /**
     * 处理类的基本用法
     */
    public static void test01() throws Exception{
    
    
        ClassPool pool = ClassPool.getDefault();
        // 加载已有类
        CtClass cc = pool.get("test.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());  // 获得接口,得到的是一个数组
    }

    /**
     * 测试添加新的方法
     */
    public static void test02() throws Exception{
    
    
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("test.Emp");

//        CtMethod m = CtNewMethod.make("public int add(int a, int b){return a+b;}", cc);

        // 声明一个方法
        // (返回类型, 方法名, 参数类型, 添加到哪个类)
        CtMethod m = new CtMethod(CtClass.intType, "add", new CtClass[]{
    
    CtClass.intType, CtClass.intType}, cc);
        // 添加方法体
        m.setModifiers(Modifier.PUBLIC);  // 访问权限
        m.setBody("{System.out.println(\"add fun\"); return $1 + $2;}");

        cc.addMethod(m);

        // 通过反射调用新生成的方法
        Class clz = cc.toClass();
        Object obj = clz.getConstructor().newInstance();  // 创建Emp对象

        Method method = clz.getDeclaredMethod("add", int.class, int.class);
        Object result = method.invoke(obj, 200, 300);
        System.out.println(result);

    }

    /**
     * 修改已有方法的信息,修改方法体的内容
     */
    public static void test03() throws Exception{
    
    
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("test.Emp");

        CtMethod cm = cc.getDeclaredMethod("sayHello", new CtClass[]{
    
    CtClass.intType});
        cm.insertBefore("System.out.println($1); System.out.println(\"start !!!\");");
        // 在原文件的指定行数添加代码
        cm.insertAt(9, "int b = 3;System.out.println(\"b = \" + b);");
        cm.insertAfter("System.out.println(\"end !!!\");");

        // 通过反射调用新生成的方法
        Class clz = cc.toClass();
        Object obj = clz.getConstructor().newInstance();  // 创建Emp对象

        Method method = clz.getDeclaredMethod("sayHello", int.class);
        method.invoke(obj, 300);

    }

    /**
     * 属性的操作
     */
    public static void test04() throws Exception{
    
    
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("test.Emp");

//        CtField f1 = CtField.make("private int salary = 1000;", cc);
        CtField f1 = new CtField(CtClass.intType,"salary",cc);
        f1.setModifiers(Modifier.PRIVATE);
        cc.addField(f1, "1000");

        // 增加相应的set/get方法
        cc.addMethod(CtNewMethod.getter("getSalary", f1));
        cc.addMethod(CtNewMethod.setter("setSalary", f1));

        CtField f2 = cc.getDeclaredField("salary");  // 获取指定属性
        System.out.println(f2.getName());

        // 反射
        Class clz = cc.toClass();
//        Emp emp = (Emp)clz.getConstructor().newInstance();
        Object emp = clz.getConstructor().newInstance();

        Field sf = clz.getDeclaredField("salary");
        sf.setAccessible(true);    // 设置这个属性不需要做安全检查了,可以直接访问
        System.out.println(sf.get(emp));

    }

    /**
     * 构造器方法的操作
     */
    public static void test05() throws Exception{
    
    
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("test.Emp");

        CtConstructor[] cs = cc.getConstructors();
        for (CtConstructor c: cs) {
    
    
            System.out.println(c.getLongName());
//            c.insertBefore(...);
        }


    }

    public static void main(String[] args) throws Exception{
    
    

//        test01();  // testXX 不能同时调用
//        test02();
//        test03();
//        test04();
        test05();
    }
}

Output

test01

在这里插入图片描述

扫描二维码关注公众号,回复: 12657490 查看本文章

test02

在这里插入图片描述

test03

在这里插入图片描述

test04

在这里插入图片描述

test05

在这里插入图片描述


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46456049/article/details/113880539