字节码增强技术-Javassist

本文介绍了字节码增强技术的重要性,并重点讲解了 Javassist 框架。通过三个示例,包括入门 Demo、Http Client 增强以及实现动态代理,展示了如何使用 Javassist 进行字节码操作。Javassist 以其简单易用和高效性能,成为 Java 字节码增强的有力工具。
摘要由CSDN通过智能技术生成

字节码

什么是字节码,在这里就不在赘述了,网上教程很多。Java 为了能让 Java 程序编译一次到处运行,用 Java 编译器将程序对源代码编译生成固定格式的字节码(.class文件)供 JVM 使用,因此理论上来说,只要符合 JVM 规范的字节码文件,就可以在 JVM 上运行,不同的 JVM 类语言(如Scala、Groovy、Kotlin)编译成字节码都可在 JVM 运行,除此之外,如果你对 JVM 的字节码规范非常了解的话,通过自己按照 JVM 规范自己写也是可以的。

那么什么是字节码增强呢?简单理解就是通过某种手段或者技术修改编译好的字节码,让新生成的字节码能满足我们的定制需求,这里说的需求就有很多了,比如常用的 AOP 底层很多就是使用字节码增强来达到切面拦截,再比如微服务中的链路追踪就使用了字节码增强(仅仅只一些 Java 客户端)来进行埋点标记来记录调用链关系的,所以了解字节码增强对一些框架能有更深入对理解,对问题排查有很大对帮助。

上面说的通过某种手段或者技术到底指哪些呢?我们最常用的 Java Proxy 也是一种增强技术,另外常用的还有 ASM,AspectJ,Javassist等常用的技术,其中ASM在指令层次操作字节码的,需要对JVM的指令有一定的了解,同时众多的指令也很难记住,操作比较高;AspectJ扩展了 Java,定义了一些专门的AOP语法,其中 Spring AOP 就使用了 AspectJ;Javassist 是强调源代码层次操作字节码的框架,操作起来很容易入手。

Javassist

使用Javassist需要使用javassist.jar。

优势:

  • 操作简单,容易上手
  • 性能高于反射

缺点:

  • 性能相比 ASM ,会低一些
  • 不支持 continue 和 break 表达式,不支持内部类和匿名类,因此在有些场景是不适合的

Javassist 使用 ClassPool 来操作所有的 Java 类。这个类的工作方式与 JVM 类装载器非常相似,但是有一个重要的区别是它不是将装载的、要执行的类作为应用程序的一部分链接,类池使所装载的类可以通过 Javassist API 作为数据使用。可以使用默认的类池(ClassPool.getDefault()),它是从 JVM 搜索路径中装载的,也可以定义一个搜索您自己的路径列表的类池。甚至可以直接从字节数组或者流中装载二进制类,以及从头开始创建新类。

装载到类池中的类由 CtClass 实例表示。与标准的 Class 类一样, CtClass 提供了检查类数据(如字段和方法)的方法。不过,这只是 CtClass 的部分内容,它还定义了在类中添加新字段、方法和构造函数、以及改变类、父类和接口的方法。

字段、方法和构造函数分别由 CtField、CtMethod 和 CtConstructor 的实例表示。这些类定义了修改由它们所表示的对象的所有方法的方法,包括方法或者构造函数中的实际字节码内容。

Javassist 常用类的说明:

  • CtClass(compile-time class):编译时类信息,它是一个class文件在代码中的抽象表现形式,可以通过一个类的全限定名来获取一个CtClass对象,用来表示这个类文件。
  • ClassPool:ClassPool是一张保存CtClass信息的HashTable,key为类的全限定名称,value为类名对应的CtClass对象。当我们需要对某个类进行修改时,就是通过pool.getCtClass(“className”)方法从pool中获取到相应的CtClass。
  • CtMethod、CtField:这两个比较好理解,对应的是类中的方法和属性,可以用于定义或者修改一些方法和字段。

Javassist 增强的代码片段是使用字符串来编写的,基本和平时写的 Java 源代码一致,主要的不同是一些是以 $ 开头的标识符,用于表示方法或者构造函数参数、方法返回值等。

比如:


public void method1(String arg1, Object arg2) {
    // 增强代码片段
    {
        System.out.println("入参 1: "   $1); // arg1
        System.out.println("入参 2: "   $2); // arg2
    }
}

入门 Demo

通过一个平时经常需要用的业务日志记录来学习,平时业务日志操作记录基本都是通过 AOP 实现的,这次就使用字节码增强技术来进行实现,对业务代码基本无任何侵入。

首先定义一个业务 service

public clas
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值