news 2026/6/15 0:50:33

Dexmaker实战指南:Android动态代码生成的终极武器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Dexmaker实战指南:Android动态代码生成的终极武器

Dexmaker是一个专为Android平台设计的Java语言API,用于在编译时或运行时生成针对Dalvik虚拟机的代码。与cglib或ASM等传统代码生成库不同,Dexmaker直接创建Dalvik的.dex文件而非Java的.class文件,这在Android开发领域具有独特价值。

【免费下载链接】dexmaker项目地址: https://gitcode.com/gh_mirrors/dex/dexmaker

核心功能深度解析

动态字节码生成能力

Dexmaker提供了接近底层的API,这些API镜像了Dalvik字节码规范,让你能够精确控制生成的字节码。代码是逐条指令生成的,如果你需要抽象语法树,需要自行构建。由于它使用Dalvik的dx工具作为后端,你可以免费获得高效的寄存器分配和常规/宽指令选择。

应用场景示例

  • 在运行时生成适配特定业务逻辑的类
  • 为测试框架创建动态Mock对象
  • 实现AOP(面向切面编程)功能

Mockito集成支持

Dexmaker通过生成Dalvik字节码类代理,让你能够在Android项目中使用Mockito模拟库。只需在androidTestImplementation中添加对dexmaker-mockito的依赖,就可以在Android Instrumentation测试中使用Mockito。

高级Mocking功能

从Android "P"开始,使用dexmaker-mockito-inline库可以模拟final类和final方法。如果你在运行Android P或更高版本的设备或模拟器上执行测试,可以添加对dexmaker-mockito-inline的依赖,然后就可以在Android Instrumentation测试中使用正常的Mockito API来模拟final类和final方法。

实际应用案例演示

基础代码生成示例

让我们通过一个简单的HelloWorld示例来了解Dexmaker的基本用法:

public final class HelloWorldMaker { public static void main(String[] args) throws Exception { DexMaker dexMaker = new DexMaker(); // 生成HelloWorld类 TypeId<?> helloWorld = TypeId.get("LHelloWorld;"); dexMaker.declare(helloWorld, "HelloWorld.generated", Modifier.PUBLIC, TypeId.OBJECT); generateHelloMethod(dexMaker, helloWorld); // 创建dex文件并加载 File outputDir = new File("."); ClassLoader loader = dexMaker.generateAndLoad(HelloWorldMaker.class.getClassLoader(), outputDir, outputDir); Class<?> helloWorldClass = loader.loadClass("HelloWorld"); // 在进程中执行新生成的代码 helloWorldClass.getMethod("hello").invoke(null); } private static void generateHelloMethod(DexMaker dexMaker, TypeId<?> declaringType) { // 查找过程中需要的类型 TypeId<System> systemType = TypeId.get(System.class); TypeId<PrintStream> printStreamType = TypeId.get(PrintStream.class); // 在declaringType上识别'hello()'方法 MethodId hello = declaringType.getMethod(TypeId.VOID, "hello"); // 在dexMaker上声明该方法 Code code = dexMaker.declare(hello, Modifier.STATIC | Modifier.PUBLIC); // 预先声明所有需要的局部变量 Local<Integer> a = code.newLocal(TypeId.INT); Local<Integer> b = code.newLocal(TypeId.INT); Local<Integer> c = code.newLocal(TypeId.INT); Local<String> s = code.newLocal(TypeId.STRING); Local<PrintStream> localSystemOut = code.newLocal(printStreamType); // 生成具体的字节码指令 code.loadConstant(a, 0xabcd); code.loadConstant(b, 0xaaaa); code.op(BinaryOp.SUBTRACT, c, a, b); MethodId<Integer, String> toHexString = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT); code.invokeStatic(toHexString, s, c); FieldId<System, PrintStream> systemOutField = systemType.getField(printStreamType, "out"); code.sget(systemOutField, localSystemOut); MethodId<PrintStream, Void> printlnMethod = printStreamType.getMethod( TypeId.VOID, "println", TypeId.STRING); code.invokeVirtual(printlnMethod, null, localSystemOut, s); code.returnVoid(); } }

斐波那契数列生成器

为了进一步说明API的使用方式,让我们用Dexmaker生成一个等效于以下Java源码的类:

public class Fibonacci { public static int fib(int i) { if (i < 2) { return i; } return fib(i - 1) + fib(i - 2); } }

项目集成与配置

依赖管理

对于Mockito支持,通过Maven下载最新的jar包:

<dependency> <groupId>com.linkedin.dexmaker</groupId> <artifactId>dexmaker-mockito</artifactId> <version>2.28.3</version> <type>pom</type> </dependency>

或者使用Gradle:

androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.28.3'

快照版本使用

你可以使用快照构建来测试最新的未发布更改。只需将Sonatype快照仓库添加到你的Gradle脚本中:

repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } }

进阶使用技巧

共享类加载器配置

如果一个类想要调用另一个类的包私有方法,它们需要共享一个类加载器。一个常见的情况是模拟类想要模拟原始类的包私有方法。使用setSharedClassLoader方法可以设置共享的类加载器。

受信任标记

在某些情况下,你可能需要将生成的类标记为受信任的,以便它们可以调用隐藏的API。这对于在系统类上进行特殊操作是必需的,因为这些类的真实方法可能会调用受限API。

常见问题与解决方案

兼容性问题

  • Android版本限制dexmaker-mockito-inline功能需要Android P引入的OS API,无法在旧版本Android上工作。

性能优化建议

  • 在生成大量类时,合理使用共享类加载器可以减少内存占用
  • 对于频繁使用的生成类,考虑预编译并缓存结果

最佳实践总结

Dexmaker作为Android平台上的动态代码生成工具,在测试框架开发、运行时代码生成等场景中发挥着重要作用。通过掌握其核心API和使用技巧,开发者可以构建更加灵活和强大的Android应用。记住,合理使用动态代码生成能够显著提升应用的适应性和可测试性。

【免费下载链接】dexmaker项目地址: https://gitcode.com/gh_mirrors/dex/dexmaker

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 4:41:44

中国人工智能战略的本质、挑战与战略转向:基于鸽姆智库(GG3M)框架的批判性重构

超越“致命短板”&#xff1a;中国人工智能战略的批判性重构与文明级转向——基于GG3M框架的破局之路 摘要&#xff1a; 本报告批判性审视了施密特对中国AI“致命短板”的论断&#xff0c;指出其基于美国静态范式的片面性。报告承认中国在金融深度、创新生态与制度效率上与美国…

作者头像 李华
网站建设 2026/6/15 0:13:43

Python3.9 + Miniconda 搭建深度学习环境全攻略

Python3.9 Miniconda 搭建深度学习环境全攻略 在人工智能项目开发中&#xff0c;最让人头疼的往往不是模型设计本身&#xff0c;而是“我的代码在别人机器上跑不起来”——依赖版本冲突、库缺失、Python 版本不兼容……这些问题反复出现&#xff0c;严重拖慢研发进度。有没有一…

作者头像 李华
网站建设 2026/6/9 19:55:43

基于spring和vue的化妆品销售网站[VUE]-计算机毕业设计源码+LW文档

摘要&#xff1a;随着互联网技术的飞速发展和消费者购物习惯的转变&#xff0c;化妆品电子商务市场呈现出蓬勃发展的态势。为了提高化妆品销售效率、优化用户体验&#xff0c;本文设计并实现了基于Spring和Vue的化妆品销售网站。该网站利用Spring框架强大的后端处理能力&#x…

作者头像 李华
网站建设 2026/6/13 16:21:51

3大Kafka消费性能瓶颈突破技巧:告别频繁Rebalance的终极指南

你是否遇到过Kafka消费者频繁触发rebalance、消息积压持续增长&#xff0c;或者监控面板上消费延迟曲线不断飙升&#xff1f;这些问题背后往往隐藏着批量消费配置不当的核心症结。本文将从问题诊断到实战验证&#xff0c;带你系统化突破Kafka消费性能瓶颈。 【免费下载链接】ka…

作者头像 李华
网站建设 2026/6/15 14:59:24

OpenLLMetry:基于OpenTelemetry的LLM应用观测性解决方案

OpenLLMetry&#xff1a;基于OpenTelemetry的LLM应用观测性解决方案 【免费下载链接】openllmetry Open-source observability for your LLM application, based on OpenTelemetry 项目地址: https://gitcode.com/gh_mirrors/op/openllmetry 项目概述 OpenLLMetry是一个…

作者头像 李华
网站建设 2026/6/15 0:16:16

Android数据库调试革命:告别adb命令,拥抱可视化调试新时代

Android数据库调试革命&#xff1a;告别adb命令&#xff0c;拥抱可视化调试新时代 【免费下载链接】Android-Debug-Database Android Debug Database是一个Android应用程序&#xff0c;用于查看和编辑SQLite数据库文件。它可以显示数据库的结构、执行SQL查询和修改数据。这个工…

作者头像 李华