Byte Buddy

关注
义项:Java字节码生成库
Byte Buddy

Byte Buddy是面向Java虚拟机的一种运行时代码生成与字节码操作库,可以在不需要编译器参与的情况下,在Java应用运行期间创建新类或修改已有的类。[1]与Java类库自带的相关工具相比,它能够生成任意类,而不局限于为创建运行时代理而实现接口。[1]该库由Rafael Winterhalter开发,2015年获得Oracle颁发的Duke's Choice奖,被Mockito、Hibernate、Google的Bazel构建系统等框架与工具使用。[2]

百科 图文
目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

Byte Buddy是一个用于Java虚拟机的代码生成与操作库,它能够在Java应用程序运行期间创建和修改Java类,过程中不需要编译器的参与。[1]与Java类库自带的代码生成工具不同,Byte Buddy不仅可以为实现接口以生成运行时代理,还允许创建任意类。该库在Maven等构件仓库中使用net.bytebuddy作为组织标识,以byte-buddy等名称发布,源代码以Apache 2.0许可证开放。

使用Byte Buddy并不要求使用者了解Java字节码或类文件格式,其应用程序接口以简洁易懂为设计目标,同时也保留了对自定义字节码的支持,可供需要生成特定字节码的使用者使用。[1]该库以不侵入被修改的类为设计原则,生成后的类中不会残留Byte Buddy的痕迹,因此这些类无需在类路径上保留Byte Buddy即可运行,这也是其吉祥物被选为幽灵形象的原因。[2]

原理

Byte Buddy在Java字节码层面工作,通过生成和操作字节码来实现对类的处理。由于直接针对字节码而非某一种语言,它可以与使用任意JVM语言编写的代码交互,并能在应用运行期间修改正在执行的代码,甚至包括它自身的代码。[3]

该库写在一个成熟的字节码读写库ASM之上,并有意向使用者暴露ASM的应用程序接口,以便进行更底层的类型操作;直接使用ASM仍是可选的,多数使用者通常不需要用到它。[4]为避免与旧版本ASM产生版本冲突,Byte Buddy默认把ASM依赖重新打包进自己的命名空间,另有一个byte-buddy-dep构件显式依赖ASM,此时使用者也必须把Byte Buddy与ASM一并重新打包。[4]

使用者通过ByteBuddy类这一配置入口,以方法链方式描述要生成的类型,例如声明父类、用ElementMatchers挑选要处理的方法、再指定方法的实现方式,最后完成生成并把类加载进类加载器。[1]库中提供了大量预置且经过测试的元素匹配器,可以方便地组合使用。[2]除生成子类外,Byte Buddy还能重定义已有代码,既可以通过手工方式修改类,也可以借助Java代理或构建过程完成。

发展历程

Byte Buddy的起点是作者对代码生成库cglib的不满。当时他正在开发一个代理组件,需要保留被代理方法的注解,而代理通常以子类方式实现,方法注解不会被子类继承,这一限制使许多把注解作为接口一部分的库无法正常工作;他因此写了一个小库来替代已被放弃维护的cglib,后来演变为Byte Buddy。[5]

作者Rafael Winterhalter于2014年开始开发Byte Buddy,2015年发布了第一个非测试版本。[3]2015年10月,该库获得了Oracle颁发的Duke's Choice奖,获奖理由是其在Java技术方面的大量创新。[2]

此后Byte Buddy持续跟进Java平台的变化。Java 8引入接口默认方法时,该库需要相应调整,由于实现中多处默认方法只定义在类层次结构中,这一改动带来了较大范围的重构。[3]2018年前后的版本开始完整支持Java 11及Java 8以来的类文件与字节码新特性,包括ConstantDynamic和Nestmates,并逐步稳定了对Java模块系统的支持,同时保持对Java 6、7、8的兼容。

版本迭代也反映在各发行版仓库中,例如Oracle Linux 8在2020年2月出现1.10.1版本的软件包,Fedora 41在2024年10月打包1.14.2版本。[6][7]

应用

Byte Buddy主要被其他库与框架使用。Hibernate用它实现实体代理,并借助它完成对代码库的增强,通过在类中安装回调来更好地监控对象状态;Mockito用它生成模拟类,在Mockito 2中新的模拟器还会在运行时内联模拟逻辑,从而可以模拟final类和方法,这对Kotlin等默认所有方法均为final的JVM语言尤为重要。[5]

该库也用于开发Java代理,以改变整个应用程序的行为。Java代理是普通的Java程序,可以在运行时修改已有应用的代码,其premain方法与Java的main方法类似,作为入口接收Instrumentation接口实例,从而接入JVM运行时类重定义的标准接口;APM类工具借助这类代理在运行期间收集应用的度量指标。[4]

除运行时使用外,Byte Buddy还提供了Maven和Gradle插件,可以在构建过程中对类进行修改。[4]其官网将Mockito、Hibernate、Google的Bazel构建系统等列为使用者,并称该库每年的下载量超过7500万次。[2]

局限

Byte Buddy需要为每一个Java版本适配类文件格式的变化,这类变化有时并不简单。作者曾指出,Java 8引入的接口默认方法看起来只是小改动,却要求对实现做大量重构;随着Java发布节奏加快,维护适配的工作量也随之增加。[3]

由于许多库依赖Byte Buddy,新的Java主要版本发布后,依赖它的库必须等待其更新才能支持新版本,而Maven等工具本身对新Java版本的支持也存在滞后,这些因素都会制约适配速度。[3]

不同JVM语言对字节码转换的处理方式存在差异,部分语言会尝试模拟某些行为,这可能导致Byte Buddy执行特定任务失败,因此对Kotlin、Scala等语言的支持长期是功能请求的常见内容。在Nestmates方面,Byte Buddy可以支持已有的嵌套类关系,但在一段时间内其领域特定语言并不允许修改或新增这类关系。

此外,在类中新增方法等操作可能改变类的隐式序列化标识,使用相关功能时需要考虑这一影响。[8]

参见

  • ASM —— Byte Buddy 实现所依赖的字节码读写库,其接口也被有条件地暴露给使用者。

  • Java字节码 —— Byte Buddy 直接生成和操作的对象,是其与各类 JVM 语言交互的基础。

  • Java虚拟机 —— Byte Buddy 运行的平台,提供运行时类重定义等标准接口。

  • Mockito —— 使用 Byte Buddy 生成模拟类的测试框架。

  • Hibernate —— 使用 Byte Buddy 实现实体代理的持久化框架。

  • Oracle —— 于 2015 年向 Byte Buddy 颁发 Duke's Choice 奖的机构。

参考资料

  1. bytebuddy.net 上的网页 [引用日期2026-10-14]
  2. Welcome, I'm your Byte Buddy! [引用日期2026-10-14]
  3. 最新版Byte Buddy完全支持Java 11 [引用日期2026-10-14]
  4. byte-buddy [引用日期2026-10-14]
  5. Meet Rafael Winterhalter and Byte Buddy - In Relation To [引用日期2026-10-14]
  6. oracle.com 上的网页 [引用日期2026-10-14]
  7. byte-buddy-1.14.2-9.fc41~bootstrap.noarch.rpm [引用日期2026-10-14]
  8. stackoverflow.com 上的网页 [引用日期2026-10-14]
词条评价
词条统计

浏览次数:3 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-13T21:25:17Z

历史版本

本条目引用的词条
Java字节码 ASM Oracle Hibernate Mockito Bazel Java虚拟机