从Java 源代码到机器码ELF/OAT的演进过程中核心在于 Android 虚拟机从 Dalvik 到 ART如何不断平衡“编译速度”、“运行性能”和“存储空间”的关系。以下是整个链路的详细拆解1. 编译期从 Java 到 Dex (打包阶段)这是开发者在电脑上完成的过程。Java 源代码 (.java) -字节码 (.class)使用javac将代码编译成标准 Java 字节码。字节码 (.class) - Dalvik 字节码 (.dex)使用d8以前是dx工具。这一步是 Android 的关键优化寄存器指令集标准 Java 字节码是基于“栈”的而 Dex 是基于“寄存器”的更符合物理 CPU 的运行逻辑。常量池合并将所有.class文件中的重复常量合并极大地减小了 APK 体积。打包成 .apk将classes.dex、资源文件、动态库.so打包成压缩包并签名。2. 运行期前奏从 Dex 到 Odex (安装/预编译阶段)当 APK 到达手机后系统不能直接运行“压缩包”里的代码需要经过dexopt优化或dex2oat预编译。Odex 的本质Odex(Optimized Dex) 的含义在 Android 演进中发生了变化Dalvik 时代Odex 只是对 Dex 进行了简单的校验和指令替换本质还是字节码。ART 时代 (Android 5.0)Odex 变成了一个包含本地机器码Native Code的容器。3. 核心转换从 Dex 到 ELF/Oat (编译原理)现在的 Android 系统使用ART (Android Runtime)。它在安装或后台充电时会调用dex2oat工具。编译流程Frontend前端解析classes.dex构建代码控制流图CFG。Optimization优化内联Inlining把你之前想要强制修改的inline_max_code_units应用在这里。将小函数直接嵌入调用处减少函数调用开销。指令重排、死代码删除。Backend后端针对手机 CPU 架构如 ARM64将优化后的中间代码转换成特定的机器指令。生成 ELF 文件最终生成的文件通常后缀仍叫.odex或.oat实际上遵循标准的ELF (Executable and Linkable Format)格式。代码段 (.text)里面是直接给 CPU 运行的二进制指令。数据段存储代码依赖的常量和类信息。Vdex 文件为了加快下次编译速度系统还会生成一个.vdex存储原始 Dex 信息。4. 运行态执行过程当用户点击图标启动 App 时加载系统通过mmap将 ELF 文件Odex映射到内存中。符号链接解决代码中对系统库如framework.jar的调用地址。执行AOT (Speed 模式)CPU 直接跳转到 ELF 文件中的代码段开始运行机器码。JIT (混合模式)如果没预先编译虚拟机先解释执行 Dex 字节码同时监测“热点代码”在后台偷偷把经常运行的部分编译成机器码。总结文件演进关系表阶段文件格式核心内容谁来读取开发环境.java程序员写的代码编译器安装包内.dexDalvik 字节码虚拟机优化产物.vdex原始 Dex 校验码编译器 (加速下次编译)最终形态.odex(ELF)ARM 机器指令手机 CPU (直接运行)
Java到机器码:Android虚拟机的性能进化
从Java 源代码到机器码ELF/OAT的演进过程中核心在于 Android 虚拟机从 Dalvik 到 ART如何不断平衡“编译速度”、“运行性能”和“存储空间”的关系。以下是整个链路的详细拆解1. 编译期从 Java 到 Dex (打包阶段)这是开发者在电脑上完成的过程。Java 源代码 (.java) -字节码 (.class)使用javac将代码编译成标准 Java 字节码。字节码 (.class) - Dalvik 字节码 (.dex)使用d8以前是dx工具。这一步是 Android 的关键优化寄存器指令集标准 Java 字节码是基于“栈”的而 Dex 是基于“寄存器”的更符合物理 CPU 的运行逻辑。常量池合并将所有.class文件中的重复常量合并极大地减小了 APK 体积。打包成 .apk将classes.dex、资源文件、动态库.so打包成压缩包并签名。2. 运行期前奏从 Dex 到 Odex (安装/预编译阶段)当 APK 到达手机后系统不能直接运行“压缩包”里的代码需要经过dexopt优化或dex2oat预编译。Odex 的本质Odex(Optimized Dex) 的含义在 Android 演进中发生了变化Dalvik 时代Odex 只是对 Dex 进行了简单的校验和指令替换本质还是字节码。ART 时代 (Android 5.0)Odex 变成了一个包含本地机器码Native Code的容器。3. 核心转换从 Dex 到 ELF/Oat (编译原理)现在的 Android 系统使用ART (Android Runtime)。它在安装或后台充电时会调用dex2oat工具。编译流程Frontend前端解析classes.dex构建代码控制流图CFG。Optimization优化内联Inlining把你之前想要强制修改的inline_max_code_units应用在这里。将小函数直接嵌入调用处减少函数调用开销。指令重排、死代码删除。Backend后端针对手机 CPU 架构如 ARM64将优化后的中间代码转换成特定的机器指令。生成 ELF 文件最终生成的文件通常后缀仍叫.odex或.oat实际上遵循标准的ELF (Executable and Linkable Format)格式。代码段 (.text)里面是直接给 CPU 运行的二进制指令。数据段存储代码依赖的常量和类信息。Vdex 文件为了加快下次编译速度系统还会生成一个.vdex存储原始 Dex 信息。4. 运行态执行过程当用户点击图标启动 App 时加载系统通过mmap将 ELF 文件Odex映射到内存中。符号链接解决代码中对系统库如framework.jar的调用地址。执行AOT (Speed 模式)CPU 直接跳转到 ELF 文件中的代码段开始运行机器码。JIT (混合模式)如果没预先编译虚拟机先解释执行 Dex 字节码同时监测“热点代码”在后台偷偷把经常运行的部分编译成机器码。总结文件演进关系表阶段文件格式核心内容谁来读取开发环境.java程序员写的代码编译器安装包内.dexDalvik 字节码虚拟机优化产物.vdex原始 Dex 校验码编译器 (加速下次编译)最终形态.odex(ELF)ARM 机器指令手机 CPU (直接运行)