☰
Byte Buddy 版本演进全解析:从 release-notes 透视 JVM 运行时字节码生成库的技术发展脉络
2026/10/15 15:52:54 网站建设 项目流程
  • 开发工具
  • 后端

【免费下载链接】byte-buddy

Runtime code generation for the Java virtual machine.

项目地址:https://gitcode.com/gh_mirrors/by/byte-buddy
点击查看免费下载

Byte Buddy 是专注于 JVM 运行时字节码生成与修改的 Java 库,其根目录下的 release-notes.md 完整记录了从 2014 年首个版本 0.1 到 2026 年 9 月 1.18.14 的全部版本迭代。本文以这份发布记录为主体脉络,结合仓库内的核心源码、构建配置与插件文档,系统梳理 Byte Buddy 十余年间的功能演进、对新版 Java 的适配策略、Agent 与构建工具链的成熟过程,帮助读者理解该库当前能力的来龙去脉,并掌握如何利用发布记录反查具体功能的实现位置。

版本时间线概览:十年演进一目了然

从 release-notes.md 可以还原出完整的版本节奏:

  • 2014 年:0.1 首个正式发布,0.2 引入@SuperCall语义调整与 Java 8 默认方法支持,0.3 增加类型重定义(redefinition)与重基(rebasing)、HotSwap 与 Java agent 接入能力,0.4 引入TypePool抽象与AnnotationDescription中间表示,0.5 推出AgentBuilderAPI 与ElementMatcher匹配 DSL。
  • 2015 年:0.6 系列大规模重构命名(Instrumentation→Implementation、Field→FieldProxy),0.7 系列为泛型支持(generic types)、桥接方法(bridge methods)、MethodGraph.Compiler铺路,同年 10 月 Byte Buddy 获得 Oracle 颁发的 Duke's Choice 奖。
  • 2016 年:1.0.0 正式版支持类型注解(type annotations);1.3 系列集中打磨Advice组件(entry/exit advice、异常抑制、帧计算);1.4 系列完善AgentBuilder的 redefinition/retransformation 策略、TypePool惰性解析与 Jigsaw 模块初步支持。
  • 2017—2019 年:1.6 引入InjectingClassLoader与 Java 9 模块适配;1.7 推出MemberSubstitution、MemberRemoval;1.8 系列新增ClassWriterStrategy、ClassFileBufferStrategy,并将字节码基线下调至 Java 5;1.9 引入Plugin.Engine静态增强引擎,重做 Maven/Gradle 构建插件,加入 JNA 驱动的 attach 模拟机制。
  • 2020—2022 年:1.10 支持 Java 16、sealed types、records;1.11 引入JavaDispatcher、AccessControllerPlugin、Advice.Exit/Local注解;1.12 完善MemberSubstitution.Step、引入ConstantValueAPI、新增 Gradle 增量构建与 Android 插桩;1.14 推出AsmClassWriter/AsmClassReader抽象与PatchMode。
  • 2023—2026 年:1.15 支持 multi-release JAR 与ByteBuddyJarsTask;1.16 集成 JDK Class File API;1.17 引入@Handle、@DynamicConstant注解与LazinessMode;1.18 系列聚焦供应链安全(Sigstore 签名、SBOM)、Kotlin/AGP 支持、Windows ARM64 动态 attach,并确立*-jdk5版本命名新概念。

当前仓库根目录 pom.xml 中的版本为1.18.15-SNAPSHOT,与发布记录的最新正式版 1.18.14 正好衔接,说明 release-notes 覆盖了仓库全部已发布版本。

对新版 Java 的持续适配:类文件版本与 ASM 同步升级

发布记录中占比最大的主题是对新版 Java 的跟进,其节奏基本是「新 JDK 发布 → 更新 ASM → 增加ClassFileVersion常量 → 发布支持版本」:

功能支持引入版本发布记录中的依据
Java 24(非实验性)1.15.42024-09 条目
Java 231.14.12 / 1.14.162024-02 与 2024-05 条目
Java 221.14.82023-08 条目
Java 211.14.32023-03 条目
Java 201.12.182022-10 条目
Java 191.12.92022-04 条目
Java 181.11.62021-07 条目
Java 171.10.212021-02 条目
Java 16(实验性)1.10.122020-06 条目
Java 15(实验性)1.10.62019-12 条目
Java 141.9.142019-07 条目
Java 131.9.72019-01 条目
Java 12(初步)1.8.152018-07 条目
Java 11(非实验)1.9.02018-09 条目(ASM 7)

在源码层面,ClassFileVersion.java 定义了从JAVA_V1到JAVA_V28的完整常量,与发布记录中的 Java 版本适配一一对应。构建根目录 pom.xml 中的<version.asm>9.11</version.asm>表明当前基线使用 ASM 9.11,同时内置了 ASM 到 JDK Class File API 的桥接(version.asmjdkbridge),这正是 1.16.0 条目「Include support for JDK Class File API」的实现基础。发布记录还显示,从 1.17.0 起 Byte Buddy 依赖 Class File API 支持来覆盖「此前未知的类文件特性」,而无需等待 ASM 先行支持。

值得注意的兼容性细节:1.18.3 条目提到「在引导类加载器上加载 Byte Buddy 且 multi-release jar 不可用时,避免使用 Class File API」,说明这类桥接是按运行时环境动态降级的。

Advice组件的进化史:从 ASM 适配器到注解驱动的内联插桩

Advice是 Byte Buddy 用于在方法入口/出口注入代码的核心组件,发布记录从 1.3.0 一直跟踪到 1.18.5:

  • 1.3.0首次引入 ASM 适配器形式的Advice;
  • 1.3.7增加@Advice.Ignored与@Advice.Origin注解,实现帧信息复用;
  • 1.3.11支持@Advice.BoxedReturn、@Advice.BoxedArguments,异常处理从「前置」改为「追加」到既有 handler 之后;
  • 1.4.8允许 entry advice 通过返回值跳过原方法执行,并允许 advice 方法跨多个类分布;
  • 1.5.5重构为基于StackManipulation与Assigner的架构;
  • 1.8.12新增@Advice.Exit与@Advice.Local,支持基于 exit advice 值的重复执行;
  • 1.11.19增加@Advice.AssignReturned后处理器,允许 entry/exit 双侧声明@Advice.Local;
  • 1.14.2修复局部变量数组重映射的偏移计算,skipOn/repeatOn支持从返回数组中按索引取值;
  • 1.17.0引入@Handle与@DynamicConstant,允许在Advice中注入常量池存储的方法句柄与动态常量;
  • 1.18.5补全了Advice的hashCode/equals计算中缺失的父类。

源码 Advice.java 完整呈现了这套注解体系:@OnMethodEnter、@OnMethodExit、@This、@Argument、@AllArguments、@Return、@Thrown、@FieldValue、@FieldGetterHandle、@FieldSetterHandle、@SelfCallHandle、@Handle、@DynamicConstant、@Origin、@Enter、@Exit、@Local、@StubValue、@Unused以及AssignReturned子注解(@AsScalar、@ToArguments、@ToAllArguments、@ToThis、@ToFields、@ToReturned、@ToThrown)均为RetentionPolicy.RUNTIME。Advice同时实现了AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper与Implementation两个接口,印证了发布记录中「Advice 可作 ASM 访问器、也可作为Implementation包装器」的双重定位(1.5.3 条目)。

MemberSubstitution:从字段/方法替换到指令级编程

MemberSubstitution允许对类文件中的成员访问进行替换与委托,是发布记录中迭代最密集的组件之一:

  • 1.7.0引入首个版本,用于替换字段/方法访问;
  • 1.9.2支持委托到匹配到的成员;
  • 1.12.8将Step类型按预期公开,并补充常用默认Step(1.12.23);
  • 1.13.0API 趋于完整,保留原始调用指令、支持构造器作为替换目标、引入ConstantValue统一常量解析;
  • 1.14.0新增Step.Factory.ForDelegation,实现类似MethodDelegation的代码内委托;
  • 1.14.19允许在MemberSubstitution中加载被插桩方法的参数;
  • 1.17.0支持拦截invokedynamic指令,并引入@Handle、@DynamicConstant注解。

源码 MemberSubstitution.java 中可见Step<U extends Target>工厂接口(第 1903 行)以及@This、@Argument、@AllArguments、@FieldValue、@Handle、@DynamicConstant、@SelfCallHandle、@FieldGetterHandle、@FieldSetterHandle、@Origin、@Unused、@StubValue、@Current等绑定注解,与 1.14.0「添加 handlers 以利用方法句柄进行字段访问与自调用」的条目相互印证。结合 1.17.3 条目「进一步泛型化MemberSubstitutionAPI」,可以看出该组件正逐步演进为覆盖字段、方法、构造器、invokedynamic的全方位字节码替换工具。

Java Agent 与动态 Attach:多平台、多 JVM 的适配历程

Agent 能力是 Byte Buddy 实现已加载类重定义的基础,发布记录体现了对 HotSpot、OpenJ9/J9、Windows/POSIX 各组合的长期打磨:

  • 1.9.15增加基于 JNA 的 HotSpot Windows attach 模拟与 OpenJ9/J9 的 POSIX/Windows attach 模拟;
  • 1.9.16支持 Solaris 上的 attach 模拟,修正 POSIX 的 JNA 签名;
  • 1.10.1引入jdk.internal.misc.Unsafe注入 API(AgentBuilder.InjectionStrategy),支持平台缺少jdk.unsupported时仍可注入;
  • 1.10.9修正 MacOS 临时目录发现;
  • 1.11.14增加事后封闭未密封类加载器(seal unsealed class loaders)的能力;
  • 1.14.14修复 Windows 服务用户场景下的动态 attach;
  • 1.14.18修复CircularityLock在加锁期间加载类的问题,attach 模拟在无stat命令时改用istat;
  • 1.18.12通过发布win32-aarch64原生attach_hotspot_windows库,支持 Windows ARM64 动态 attach;
  • 1.18.14避免外部 attach 时在派生子进程命令行暴露 agent 参数。

ByteBuddyAgent.java 的类注释给出了标准用法:

java -javaagent:byte-buddy-agent.jar -jar app.jar

源码同时定义了Agent-Class、Can-Redefine-Classes、Can-Retransform-Classes、Can-Set-Native-Method-Prefix等 manifest 属性常量(第 87—102 行),对应 1.9.0 条目「为byte-buddy与byte-buddy-agent构件添加module-info.class」及 1.18.1「修复生成的 module-info 以包含新包」等后续完善。Windows ARM64 的原生实现位于 attach_hotspot_windows.c,而VirtualMachine、Attacher、Installer等类共同构成 agent 的安装与外部 attach 基础设施。

构建期增强:Maven、Gradle 与 Android 插件的成熟路径

发布记录显示构建工具链自 1.4.21/1.4.22 引入 Maven 与 Gradle 插件后持续演进:

  • 1.9.0引入Plugin.Engine统一静态增强引擎,Maven/Gradle 插件均改为基于它实现;
  • 1.12.15支持从 Gradle 插件进行 Android 插桩;
  • 1.15.0Android 插件获得标准配置扩展,行为对齐普通 Gradle 插件;
  • 1.15.2增加ByteBuddyJarsTask,支持一次转换多个 jar;
  • 1.15.11Plugin.Engine可链接文件而非复制,Android 插件支持变体配置;
  • 1.16.0Plugin.Engine支持保留文件夹;
  • 1.18.9支持 AGP9 及以上版本的 Android 库;
  • 1.18.12Gradle 插件自动支持 Kotlin;1.18.13修正 Kotlin 的 classes 目录重定向并兼容旧版 Gradle,任务优先使用 Gradle 任务注册 API。

Maven 插件的实操配置可见 byte-buddy-maven-plugin/README.md,其transformgoal 的标准配置如下:

<build> <plugins> <plugin> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-maven-plugin</artifactId> <version>LATEST</version> <executions> <execution> <goals> <goal>transform</goal> </goals> </execution> </executions> <configuration> <transformations> <transformation> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>LATEST</version> <plugin>net.bytebuddy.build.CachedReturnPlugin</plugin> </transformation> </transformations> </configuration> </plugin> </plugins> </build>

该文档还说明:transform-test用于转换测试类,transform-runtime在保留运行时类的同时转换生产类,transform-extended覆盖所有非 test 作用域(对应 1.14.1 条目);插件可通过META-INF/net.bytebuddy/build.plugins文件自动发现(对应 1.12.13 条目)。在 ByteBuddyMojo.java 中可以看到transformations参数要求每个 transformation 的plugin属性必须实现Plugin接口,并可附带 groupId/artifactId/version 坐标。

Gradle 插件侧,byte-buddy-gradle-plugin/src/main/java/net/bytebuddy/build/gradle 目录下的ByteBuddyPlugin、ByteBuddyTask、ByteBuddyJarsTask、ByteBuddyJarTask、KotlinByteBuddyTaskConfiguration等类,分别对应 1.18.12 的 Kotlin 自动支持与 1.15.2 的ByteBuddyJarsTask多 jar 转换能力。

供应链安全与稳定性:1.18 系列的主题词

1.18 系列集中体现了 Byte Buddy 在供应链安全与抗畸形输入方面的投入:

  • 签名与材料:1.18.12 为发布构件加入 SBOM;1.18.13 确保 SBOM 实际包含在发布构件中;1.18.14 在既有 GPG 签名之外,使用 Sigstore 对所有部署文件签名。根目录 pom.xml 中的sigstoreprofile 与<release.profiles>extras,gpg,sigstore,gradle-release,multi-release</release.profiles>正是这条链路的构建侧配置。
  • 路径穿越防护:1.18.11 检查注入类文件的「可遍历路径」这一假设性攻击向量;1.18.13 防止复制未经转换的 jar 时传播路径穿越;1.18.14 Android 插件保留文件时校验条目名。这对应了 pom.xml 中sigstore.artifacts.skip等属性所服务的部署流程对输入完整性的整体关注。
  • 鲁棒性:1.18.14 限制泛型签名解析的嵌套深度,防止畸形 class 文件导致栈耗尽;1.18.9 在发现 Java 25 及以上时默认禁用Unsafe使用,而 1.18.10 将这一默认变更推迟到 Java 26 并改善错误信息。

版本命名新概念:*-jdk5后缀与 Java 8 基线

1.18.7 条目宣布了一个影响所有使用者的版本策略变更:「为向后兼容的 jar 引入带*-jdk5后缀的新版本概念,常规 jar 以 Java 8 为基线」。这意味着:

  • 带-jdk5后缀的构件(如byte-buddy-1.18.7-jdk5.jar)保持 Java 5 字节码基线,服务于需要运行在极老 JVM 上的场景;
  • 常规构件从该版本起以 Java 8 为基线,换取更快的类文件校验与更好的 CDS 支持(1.15.5 条目已为byte-buddy与 agent 构件引入 multi-release jar 以支持 CDS)。

构建侧的两个发布 profile 与之对应:publish-jdk5与publish-jdk8(见 pom.xml),前者维持1.5的bytecode.main.version,后者将基线提升到 8。README 中的 Java 兼容性表格同样区分了1.18.7(最低 JVM 8)与1.18.7-jdk5(最低 JVM 5)两行。

加载策略与运行时基础设施的沉淀

发布记录同样记录了运行时加载机制的演进,这在 ClassLoadingStrategy.java 中有完整对应:

  • WRAPPER:新建以目标类加载器为父的ByteArrayClassLoader,可加载存在循环加载依赖的类型,且随类加载器回收而卸载(对应 0.3 条目的 child-first 策略与 0.7 的注入顺序重构);
  • WRAPPER_PERSISTENT/CHILD_FIRST_PERSISTENT:将字节数组暴露为getResourceAsStream资源;
  • CHILD_FIRST:动态类型优先于父类加载器同名类型(不可见而非替换);
  • INJECTION:通过反射把类直接注入既有类加载器,避免新建加载器、获得包级访问能力,但自 Java 11 起受模块封装限制——这与 1.18.9「发现 Java 25 及以上默认禁用 Unsafe」、1.8.16「Java 11+ 通过Unsafe::putBoolean回退启用注入」等条目一脉相承。

此外,Nexus/Installer机制(1.7.0 的net.bytebuddy.nexus.disabled属性、0.7 的 Nexus 多代理注册)与 1.17.6 新增的TypePool.LazinessMode及AgentBuilder便捷支持,共同构成了 agent 场景下类型解析与辅助类型注入的运行时底座。

如何从发布记录反查源码:一种实用检索路径

release-notes 不仅是变更清单,也是定位源码的索引。以「某个功能在哪个类」为例:

  1. 在 release-notes 中定位引入该功能的版本号;
  2. 按版本号对照根目录 pom.xml 的发布 profile 确定当时基线;
  3. 在byte-buddy-dep/src/main/java/net/bytebuddy/下按功能域检索类名,如asm/目录下的 Advice.java、MemberSubstitution.java、AnnotationRemoval.java(1.17.5 引入),或dynamic/loading/下的 ClassLoadingStrategy.java;
  4. 再通过src/test/java下同名*Test.java确认行为契约,例如net.bytebuddy.asm.AdviceTest、net.bytebuddy.matcher.*Test等。

这种「发布记录 → 主源码 → 测试用例」的检索链,能帮助读者在阅读新增条目后迅速落到可运行的代码证据上。

结语

从 2014 年的 0.1 到 2026 年的 1.18.14,release-notes.md 勾勒出的是一条「运行时字节码生成核心 + Agent 动态插桩 + 构建期静态增强」三位一体的能力演进路线。理解这条脉络,不仅有助于评估 Byte Buddy 当前 API 的设计动机(如Advice的注解体系为何如此丰富、MemberSubstitution为何逐步覆盖invokedynamic、为何引入*-jdk5版本后缀),也能在阅读源码时快速建立「这个类解决什么问题、从哪个版本开始存在」的坐标系。对于计划将 Byte Buddy 集成到自身框架的开发者而言,这份发布记录连同仓库中的源码与插件配置,是一份可直接对照使用的技术档案。

  • 开发工具
  • 后端

【免费下载链接】byte-buddy

Runtime code generation for the Java virtual machine.

项目地址:https://gitcode.com/gh_mirrors/by/byte-buddy
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询