java 动态字节码技术javassist 动态用代码修改添加类、方法代码

本文探讨了如何利用Java的动态字节码技术,特别是ASM和Javassist库,实现在运行时修改方法逻辑,如AOP无法触及的部分。作者通过实例展示了如何使用Javassist修改User类的getUsername方法,以及ASM的底层操作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java 动态字节码技术javassist

平时我们可以使用AOP来动态的操作方法的处理过程,在before、after、around、return、throw Exception等关键时机作出处理,而AOP是没办法直接修改被代理方法内部逻辑的。当有这种需求的时候就只能使用动态字节码技术来解决了。热更新代码这些其实也是通过动态字节码技术实现的。

补充说明:java动态字节码技术目前主流的是两种,一个是ASM,一个是javassist。(两种都必须在类被加载到jvm之前去修改)

ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

依赖引入

        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>

代码

User类


/**
 * 用户类
 *
 * @author humorchen
 * @date 2021/12/29 17:05
 */
public class User {
    private String username;

    
    public User(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

}

测试类


import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

/**
 * 动态修改方法逻辑
 *
 * @author humorchen
 * @date 2021/12/29 17:05
 */
public class DynamicMethodTest {

    public static void main(String[] args) {
        //获取类池
        ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = null;
        try {
            //获取类
            ctClass = classPool.getCtClass("com.example.test.method.User");
            //获取方法
            CtMethod getUsernameMethod = ctClass.getDeclaredMethod("getUsername");
            //设置新的代码
            getUsernameMethod.setBody("return \"dynamic modified your code ,old result: \" + username;");
            //写入
            ctClass.writeFile();
            //加载该类的字节码(不能少)
			ctClass.toClass();
            //测试使用被修改后的类
            Class userClass = ctClass.toClass();
            User user = (User) userClass.newInstance();
            user.setUsername("小明");
            System.out.println(user.getUsername());

            //换一种方法使用
            User user1 = new User("小红");
            System.out.println(user1.getUsername());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果

在这里插入图片描述

ASM操作示范(更难)

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HumorChen99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值