java–字节码增强–1.1–ByteBuddy–介绍
1、介绍
- 是一个字节码生成和操作库
- 用于 在Java应用程序运行时 创建和修改Java类,而无需编译器的帮助。
- 允许创建任意类,并且不限于实现用于创建运行时代理的接口。
- 提供了一种API
- 可以使用Java代理或在构建过程中手动更改类,很容易操作字节码,控制类和方法
- 用于定义所谓的 Java 代理,该代理允许在任何 Java应用程序的运行期间 进行代码转换。
- 不仅限于创建子类和操作类,还可以转换现有代码。
1.1、官网地址
https://bytebuddy.net/
1.2、使用场景
Java 是一种强类型的编程语言,即要求所有变量和对象都有一个确定的类型,如果在赋值操作中出现类型不兼容的情况,就会抛出异常。强类型检查在大多数情况下是可行的,然而在某些特殊场景下,强类型检查则成了巨大的障碍。
我们在做一些通用工具封装的时候,类型检查就成了很大障碍。比如我们编写一个通用的Dao实现数据操作,我们根本不知道用户要调用的方法会传几个参数、每个参数是什么类型、需求变更又会出现什么类型,几乎没法在方法中引用用户方法中定义的任何类型。
我们绝大多数通用工具封装都采用了反射机制,通过反射可以知道用户调用的方法或字段,但是Java反射有很多缺陷:
- 反射性能很差
- 反射能绕开类型安全检查,不安全,比如权限暴力破解
Byte Buddy 就可以很好解决上述问题。
1.3、Byte Buddy优势
- 无需理解字节码指令,即可使用简单的 API,就能很容易操作字节码,控制类和方法。
- 支持Java 11
- 库轻量,仅取决于Java字节代码解析器库ASM的访问者API,它本身不需要任何其他依赖项。
- 性能超过以下项
- JDK动态代理
- cglib
- Javassist
2、java编程语言 代码生成库(主要的几个)
- Java Proxy
- CGLIB
- Javassist
- Byte Buddy
2.1、Java Proxy
- 是 JDK 自带的一个代理工具,它允许为实现了一系列接口的类生成代理类。
- 要求目标类必须实现接口是一个非常大限制,例如,在某些场景中,目标类没有实现任何接口且无法修改目标类的代码实现,Java Proxy 就无法对其进行扩展和增强了。
2.2、CGLIB
- 是一个相当强大的库
- 非常 复杂
- 许多用户放弃了 CGLIB
2.3、Javassist
- 对 Java开发者 来说非常友好
- 使用 Java源代码字符串 和 Javassist 提供的一些简单 API ,共同拼凑出用户想要的 Java类
- Javassist 自带一个编译器,拼凑好的 Java 类在程序运行时会被编译成为字节码并加载到 JVM 中。
- Javassist 库简单易用,而且使用 Java 语法构建类与平时写 Java 代码类似
- Javassist编译器 在性能上比不了 Javac编译器,而且在动态组合字符串以实现比较复杂的逻辑时容易出错。
2.4、Byte Buddy
- 提供了一种非常灵活且强大的领域特定语言,通过编写简单的 Java 代码即可创建自定义的运行时类。
- 具有非常开放的定制性,能够应付不同复杂度的需求。
3、性能
3.1、官网对各类库 创建动态类的运行时 的性能测试图
3.1.1、每一行说明
- 第1行:类的创建
- 第2行:接口实现
- 第3行:方法调用
- 第4行:类型扩展
- 第5行:父类方法调用的性能结果。
3.1.2、结论
从性能报告中可以看出,Byte Buddy 的主要侧重点在于以 最少的运行时间 生成代码,需要注意的是,我们这些衡量 Java 代码性能的测试,都由 Java 虚拟机即时编译器优化过,如果你的代码只是偶尔运行,没有得到虚拟机的优化,可能性能会有所偏差。所以我们在使用 Byte Buddy 开发时,我们希望监控这些指标,以避免在添加新功能时造成性能损失。