尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Byte Buddy Android:在 Android 运行时生成并加载动态类的完整实战指南
开发工具后端【免费下载链接】byte-buddyRuntime code generation for the Java virtual machine.项目地址https://gitcode.com/gh_mirrors/by/byte-buddy点击查看免费下载导读Byte Buddy 是 JVM 上的运行时字节码生成库而Byte Buddy Android则把这一能力带到了 Android 运行时它允许在 Android 应用进程内生成类并借助专用的AndroidClassLoadingStrategy将这些类加载进当前进程。本文以 byte-buddy-android/README.md 为核心结合 AndroidClassLoadingStrategy.java 的源码实现与仓库内的测试、示例工程完整讲解其用法、两种加载策略的底层原理、安全约束与适用前提。读完本文你将掌握在 Android 应用中用 Byte Buddy 完成「生成子类 → dex 编译 → 加载进当前 VM」的完整链路并能在Wrapping与Injecting两种策略之间做出正确选择。一、Byte Buddy Android 解决什么问题标准 JVM 环境下Byte Buddy 通过 ClassLoadingStrategy 将动态类型加载进类加载器例如ClassLoadingStrategy.Default.WRAPPER、INJECTION等默认策略见 byte-buddy-dep 中的 ClassLoadingStrategy.java 第 63-123 行。但 Android 的 Dalvik/ART 虚拟机并不直接执行 JVM 字节码.class而是执行经过 dex 编译的.dex文件因此 Byte Buddy 生成的 JVM class 文件不能直接加载。Byte Buddy Android正是在这一环节架起桥梁把 Byte Buddy 生成的 JVM class 文件交由 Android SDK 的dex 编译器转换为 dex 格式将 dex 打包进 jar 文件通过DexClassLoader或 dex 注入机制把类加载进当前 Android 应用进程。模块描述在 byte-buddy-android/pom.xml 中定义为 Byte Buddy Android allows for limited support of code generation on an Android runtime即它是「受限的」代码生成支持——原因在于 Android 环境的特殊限制详见下文第六节。二、快速上手最小的可运行示例README 给出了一个完整的最小示例生成一个Object的子类把toString()拦截为固定返回值然后加载并验证。ClassLoadingStrategy strategy new AndroidClassLoadingStrategy.Wrapping(context.getDir( generated, Context.MODE_PRIVATE)); Class? dynamicType new ByteBuddy() .subclass(Object.class) .method(ElementMatchers.named(toString)) .intercept(FixedValue.value(Hello World!)) .make() .load(getClass().getClassLoader(), strategy) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is(Hello World!));关键点拆解context.getDir(generated, Context.MODE_PRIVATE)在应用私有目录下创建名为generated的子目录作为加载策略的工作目录。MODE_PRIVATE保证该目录仅当前应用可访问这是安全模型的硬性要求详见第四节。new ByteBuddy().subclass(Object.class)...make()标准的 Byte Buddy 动态类型构建流程生成的是 JVM class 字节码.load(getClass().getClassLoader(), strategy)将生成的类型交给 Android 专用的加载策略而不是ClassLoadingStrategy.Default验证结果dynamicType.newInstance().toString()应返回Hello World!。单元测试印证仓库中的 AndroidClassLoadingStrategyTest.java 印证了这一调用契约testProcessing测试验证了load方法的完整流水线dexProcessor.create()创建转换会话 → 为每个类型调用conversion.register(name, byte[])→ 最终conversion.drainTo(OutputStream)把 dex 内容写入输出流第 71-93 行testStubbedClassLoading第 109-120 行则用new ByteBuddy(ClassFileVersion.JAVA_V6)实际构建了一个改写toString的子类并走完加载流程佐证了「生成 → dex → 加载」整条链路的可行性。三、两种加载策略Wrapping 与 InjectingREADME 明确指出Byte Buddy Android提供两种加载策略与 Byte Buddy 标准策略中的 wrapping 与 injection 思路相似。二者的抽象基类都是AndroidClassLoadingStrategy见 AndroidClassLoadingStrategy.java 第 80 行区别在于doLoad的实现方式。1. Wrapping创建包装类加载器AndroidClassLoadingStrategy.Wrapping源码第 666-706 行的doLoad实现为ClassLoader dexClassLoader new DexClassLoader( jar.getAbsolutePath(), // dex 所在 jar 路径 privateDirectory.getAbsolutePath(), // 优化后 dex 的输出目录 EMPTY_LIBRARY_PATH, // 空 native 库路径 classLoader); // 以传入的类加载器为父加载器随后通过Class.forName(typeDescription.getName(), false, dexClassLoader)逐个加载类型。特点每次加载都会新建一个独立的DexClassLoader加载进来的类型对该类加载器之外的代码不可见以传入的类加载器为父遵循父优先委托模型适合不想污染现有类加载器命名空间、希望动态类型可被整体卸载随类加载器一起回收的场景。2. Injecting注入到目标类加载器AndroidClassLoadingStrategy.Injecting源码第 711-921 行把类型注入到传入的类加载器本身而非新建包装加载器。其实现分两个时代Android PAPI 28及更高版本通过反射调用BaseDexClassLoader#addDexPath(String, boolean)将 dex 路径追加进目标类加载器Dispatcher.ForAndroidPVm第 861-919 行。源码在第 891-892 行做了明确校验On Android P, a class injection can only be applied to BaseDexClassLoader即目标类加载器必须是BaseDexClassLoader的子类否则抛出IllegalArgumentException旧版本 VM通过dalvik.system.DexFile.loadDex(...)加载 dex 后调用dexFile.loadClass(name, classLoader)注入Dispatcher.ForLegacyVm第 819-856 行。两个 dispatcher 通过静态块中的反射探测自动选择第 722-730 行。特点不创建新类加载器加载的类型与目标类加载器中原有类型处于同一命名空间注入的类可以访问同包下其他类的包级私有成员额外限制不能向 bootstrap 类加载器null注入。Injecting.load方法第 756-761 行会显式抛出IllegalArgumentException: Cannot inject classes into the bootstrap class loader on Android对应测试testInjectBootstrapLoader测试文件第 100-106 行也验证了这一约束。3. 两个构造函数与自定义 dex 编译器两种策略各有两个构造函数构造函数说明Wrapping(File privateDirectory)使用默认的基于 SDK dex 编译器的DexProcessorWrapping(File privateDirectory, DexProcessor dexProcessor)允许传入自定义DexProcessorInjecting(File privateDirectory)同上使用默认 dex 处理器Injecting(File privateDirectory, DexProcessor dexProcessor)允许传入自定义DexProcessor注意基类构造器第 148-155 行要求传入的目录必须真实存在且是目录否则抛出IllegalArgumentException: Not a directory ...测试testAndroidClassLoaderRequiresDirectory第 95-98 行验证了该行为。四、目录选择与 Android 安全模型重要约束源码 javadoc第 53-78 行与 README 都强调了一个关键约束加载策略必须把临时文件写入不被其他应用共享的目录。Android 的沙箱模型不允许把待加载的 dex/jar 文件放到其他应用可以篡改的位置例如外部存储否则第三方应用可替换这些文件从而破坏沙箱隔离。README 中使用的context.getDir(generated, Context.MODE_PRIVATE)正是标准做法源码 javadoc 还建议了两个合法选择android.content.Context#getDir(String, int)并以Context.MODE_PRIVATE创建私有目录Android API 21 及以上暴露的getCodeCacheDir()目录。其余细节临时文件清理load方法在 finally 块中会删除生成的临时 jar 文件源码第 184-188 行删除失败时仅记录 warning 日志。但目录本身不会被自动清理——javadoc 明确说明目录在应用退出后不会被 Byte Buddy 清理这仍是使用者的责任第 141-143 行。POSIX 权限加固源码第 107-122 行通过反射尝试调用java.nio.file.Files#setPosixFilePermissions将生成的 jar 标记为只读OWNER_READ在支持该 API 的平台上进一步加强文件防护不支持时静默退化为空操作。五、底层原理从 class 字节码到 dex 的转换链路AndroidClassLoadingStrategy.load源码第 160-189 行的完整工作流程为调用dexProcessor.create()开启一次 dex 转换会话遍历types映射对每个类型调用conversion.register(name, byte[])注册 JVM class 字节码在私有目录中创建随机命名的 jar 文件在 jar 内写入classes.dex条目DexClassLoader约定的查找路径常量DEX_CLASS_FILE第 86 行调用conversion.drainTo(jarOutputStream)把 dex 内容写出对 jar 做只读加固调用抽象方法doLoad(classLoader, typeDescriptions, jar)由Wrapping/Injecting各自实现实际加载。DexProcessor可替换的 dex 编译核心DexProcessor接口第 285-315 行抽象了「JVM class 文件 → dex 文件」的转换内置默认实现DexProcessor.ForSdkCompiler第 321-661 行基于 Android SDK 的dx 编译器API 兼容 1.7 版本工作它通过com.android.dx.cf.direct.DirectClassFile解析 JVM class 字节码再用CfTranslator.translate(...)翻译为ClassDefItem加入DexFile第 454-464 行为了兼容不同时代的 dx 库 API静态块中通过反射探测挑选三种 dispatcher第 336-369 行兼容 API 26 的ForApi26LevelCompatibleVm多一个DxContext参数、旧版ForLegacyVm以及无法匹配时的Unavailable直接抛异常makeDefault()把 dex 的目标 API 级别固定为DEX_COMPATIBLE_API_VERSION 13第 326、376-380 行以兼容内置编译器。关于 class 文件版本的说明源码 javadoc第 68-77 行特别提示内置的 dx 编译器1.7 版要求输入为 Java 6ClassFileVersion.JAVA_V6格式的 class 文件。这一点在测试中得到印证——testStubbedClassLoading使用new ByteBuddy(ClassFileVersion.JAVA_V6)构建动态类型测试文件第 110 行。该版本略显过时因为 Maven Central 上没有更新版本的 dx但它足够满足多数字节码生成场景。若需要更新版本的 dex 编译器可自行实现DexProcessor接口并委托给新版编译器若新版编译器的 API 与内置版兼容甚至只需把新版 dx 加入应用构建路径、同时排除内置版本即可详见源码 javadoc 第 70-77 行。依赖构成byte-buddy-android/pom.xml 展示了模块的关键依赖net.bytebuddy:byte-buddy核心字节码生成引擎com.google.android:androidprovided作用域Android SDK 类com.jakewharton.android.repackaged:dalvik-dxAndroid SDK 的 dex 编译器dx 工具的重新打包版本。模块还定义了java6-compatibilityprofile第 119-129 行在 JDK 1.6 下构建时回退到dalvik-dx1.0 版。六、适用前提与平台限制README 明确了两条硬性前提/限制务必在选型前确认要求 Android API 21 或更高版本Android 5.0 Lollipop。API 21 以下没有DexClassLoader的现代能力且getCodeCacheDir等私有目录 API 也不可用无法转换transform已加载的类也无法注册 Java agent。这是因为 Android 运行时没有标准的java.lang.instrumentagent 机制Instrumentation重定义类的能力在 Android 上不可用。因此 Byte Buddy Android 的适用边界是「生成并加载新类型」而不是「修改已加载类」。七、仓库内的真机验证示例为验证上述机制在真实 Android 环境下的可行性仓库提供了完整的 Android 测试应用模块byte-buddy-android-testTestActivity.java 是一个可安装运行的Activity界面提供「Run test: wrapping」和「Run test: injecting」两个按钮对应布局 main.xml点击后即执行一次完整的「生成子类 → 加载 → 实例化 → 校验toString()」流程并通过 Toast 显示成功/失败示例第 144-147 行使用MethodDelegation.to(Interceptor.class)拦截toString并借SuperCall CallableString生成辅助类型auxiliary type专门用来验证辅助类型的 dex 转换与加载也能正常工作见 Interceptor 的 javadoc第 84-89 行——这是仅用FixedValue无法覆盖的更深层场景该模块的构建由androidMaven profile 激活byte-buddy-android-test/pom.xml 第 50-57 行需本机安装 Android SDK并依赖android-maven-plugin打包 APK根 pom.xml 第 28 行也注明Builds an Android test application. An Android SDK is required for doing so. (excluded from release)即该模块不参与发布。八、使用要点速查主题结论加载策略AndroidClassLoadingStrategy.Wrapping/Injecting两种均基于DexClassLoader/ dex 注入最低 APIAndroid API 21 及以上README 明确工作目录必须是应用私有目录Context.getDir(name, MODE_PRIVATE)或getCodeCacheDir()严禁外部共享存储默认 dex 编译器Android SDK dx 编译器API 兼容 1.7要求输入 Java 6 格式 class 文件可通过DexProcessor接口替换临时文件jar 在加载完成后自动删除私有目录本身需应用自行管理清理平台限制不能重定义/转换已加载类不能注册 Java agentInjecting不能用于 bootstrap 类加载器依赖需引入byte-buddydalvik-dxAndroid SDK 依赖为provided源码入口byte-buddy-android/src/main/java/net/bytebuddy/android/AndroidClassLoadingStrategy.java测试与示例AndroidClassLoadingStrategyTest.java、TestActivity.java结语Byte Buddy Android 的定位清晰在 Android 运行时生成并加载新类而非改造已有类。它以AndroidClassLoadingStrategy为唯一入口内部串联起「JVM class → dex → jar → 类加载器」的完整转换链Wrapping与Injecting两种策略分别对应「隔离可见性」与「注入现有命名空间」两种需求。使用时的核心红线是目录必须私有Android 沙箱安全、API 必须 ≥ 21、且不要试图在 Android 上做 agent 式的类重定义。结合仓库中的单元测试与真机示例工程你可以快速验证并把它接入自己的 Android 项目中。赞分享开发工具后端【免费下载链接】byte-buddyRuntime code generation for the Java virtual machine.项目地址https://gitcode.com/gh_mirrors/by/byte-buddy点击查看免费下载相关推荐Byte Buddy终极指南如何实现Java运行时动态类生成与字节码修改Byte Buddy终极指南如何实现Java运行时动态类生成与字节码修改 Byte Buddy是一款强大的Java库专注于在运行时生成和修改Java类。它提开发工具后端Android开发终极指南Byte Buddy动态代码生成神器Android开发终极指南Byte Buddy动态代码生成神器 Byte Buddy 是Java虚拟机的运行时代码生成框架在Android开发中展现出开发工具后端如何避免Byte Buddy动态生成类的内存泄漏完整指南如何避免Byte Buddy动态生成类的内存泄漏完整指南 在Java运行时代码生成领域Byte Buddy作为一款强大的字节码操作库能够动态创建和修改类。开发工具后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

从SC1345 datasheet读懂开关电源设计:从原理到PCB Layout实战

从SC1345 datasheet读懂开关电源设计:从原理到PCB Layout实战

简介:SC1345 数据手册完整 PDF,面向智能家用摄像头、安防监控、可移动设备相机、视频电话会议及行车记录仪等嵌入式视觉产品的软硬件工程师。文档来自 SmartSens,聚焦 100 万像素 CMOS 图像传感器的电气规格、引脚定义、上电/下电时序、I2C 配…

📅 2026/10/15 17:54:04
间断伽辽金法求解声波方程:处理界面跳变的数值原理与MATLAB实现

间断伽辽金法求解声波方程:处理界面跳变的数值原理与MATLAB实现

简介:本资源是一套基于Matlab实现二维声波方程数值求解的完整代码实践包,面向计算数学、声学仿真及偏微分方程数值方法学习者,尤其适合具备基础有限元与常微分方程知识的高年级本科生或研究生开展进阶实验。资源采用间断伽辽金(DG…

📅 2026/10/15 17:54:04
AI视觉+机器人抓取:C#全栈实现产线级视觉引导定位系统与TaoToken统一Key接入

AI视觉+机器人抓取:C#全栈实现产线级视觉引导定位系统与TaoToken统一Key接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/15 17:54:04
MORE NEWS

更多资讯

📰

SHT3x温湿度传感器驱动开发:从原理到避坑全指南

简介:SHT3x 温湿度传感器代码包面向嵌入式开发初学者与物联网应用工程师,围绕盛思锐 SHT3x 高精度温湿度传感器,提供一套基于 STM32 平台的完整示例工程,帮助解决环境监测、智能家居、工业自动化等场景中温湿度数据精确采集与解析…

📰

C8051F与Keil的DFP驱动包:从设备识别到C2调试的完整排坑指南

简介:这是一份面向使用SILICON LABS C8051F系列单片机并在KEIL环境下开发的配套驱动资源包,适合嵌入式工程师、单片机爱好者及需要搭建C8051F调试环境的开发者。资源重点解决通过USB转串口连接目标板时,CP210x驱动缺失、版本不兼容导致下载与…

📰

RabbitMQ 官方教程多语言代码仓库(rabbitmq-tutorials)实战指南

示例工程 【免费下载链接】rabbitmq-tutorials Tutorials for using RabbitMQ in various ways 项目地址: https://gitcode.com/gh_mirrors/ra/rabbitmq-tutorials 点击查看 免费下载 本篇技术指南围绕开源仓库 rabbitmq-tutorials 展开,它是 RabbitMQ …

📰

部署 Hermes Agent:Windows 原生与 WSL2 完全指南(TaoToken 统一 Key 接入)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

GPT-6 Astra 与 GPT-6.1 Sol并列84.99分:2026-10-12 Smoke快测数据简报

2026-10-12 赢政指数 Smoke 快测覆盖 14 个模型,GPT-6 Astra 与 GPT-6.1 Sol 以 84.99 分并列当日首位。Smoke 为每日 10 题快测,适合观察短期信号,不等同 Full 周榜结论。 本次 Smoke 评测只覆盖代码执行和材料约束两个主榜维度,…

📰

物流管理系统前后台全栈解析:运单、权限与状态机设计

简介:一份物流管理系统前台后台的完整项目资源,面向物流信息化学习者、Java Web开发者及课程设计/毕业设计人群,用于理解订单、仓储、运输调度、货物跟踪等核心业务的前后端协作实现。压缩包共2000个文件、约65.88MB,包含以png、h…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬