apk的class是什么时候转成机器码的
Table of Contents
前文[[20250124-apk打包过程]]了解到 apk 里面最终还是 class 字节码,我们知道 CPU 只能执行机器码,那 class 是什么时候被转成机器码的呢?
1. DEX 文件生成(编译时)
- 操作:在 APK 打包过程中,Java/Kotlin 代码首先被编译为
.class
文件,然后通过 D8/R8 工具转换为 DEX(Dalvik Executable)文件。 - 结果:DEX 文件是 Android 系统专用的字节码格式,但它仍然是中间代码,而不是机器码。
- 原因:
- DEX 文件是平台无关的,可以在任何 Android 设备上运行。
- DEX 文件比机器码更紧凑,减少了 APK 的体积。
2. 机器码生成(安装时或运行时)
- 操作:DEX 文件最终会被转换为机器码,这个过程发生在应用安装时或应用运行时,具体取决于 Android 系统的版本和配置。
2.1 安装时编译(AOT - Ahead Of Time)
- 适用场景:Android 5.0(API 21)及以上版本,使用 ART(Android Runtime)时。
- 过程:
- 当用户安装 APK 时,系统会调用
dex2oat
工具将 DEX 文件编译为机器码(.oat
文件)。 - 编译后的机器码存储在设备的
/data/dalvik-cache/
目录下。
- 当用户安装 APK 时,系统会调用
- 优点:
- 应用启动时直接运行机器码,性能更高。
- 减少运行时的 CPU 和内存开销。
- 缺点:
- 安装时间较长,尤其是对于大型应用。
- 占用更多的存储空间(因为机器码比 DEX 文件更大)。
2.2 运行时编译(JIT - Just In Time)
- 适用场景:Android 7.0(API 24)及以上版本,ART 引入了 JIT 编译器作为 AOT 的补充。
- 过程:
- 在应用运行时,ART 会动态地将热点代码(频繁执行的代码)从 DEX 文件编译为机器码。
- 编译后的机器码存储在内存中,供后续执行使用。
- 优点:
- 安装时间更短,因为不需要在安装时编译所有代码。
- 节省存储空间,因为只有热点代码会被编译为机器码。
- 缺点:
- 应用启动时可能会有短暂的性能损失,因为部分代码需要在运行时编译。
2.3 混合模式(AOT + JIT)
- 适用场景:Android 7.0 及以上版本。
- 过程:
- 在安装时,系统会对部分关键代码进行 AOT 编译,以提高启动性能。
- 在运行时,系统会对热点代码进行 JIT 编译,以优化长期运行的性能。
- 优点:
- 兼顾安装时间和运行性能。
- 动态优化热点代码,提升整体性能。
3. 为什么需要转换为机器码?
- 性能:机器码是 CPU 直接执行的指令,运行速度比解释执行的字节码快得多。
- 效率:通过 AOT 或 JIT 编译,可以减少运行时的 CPU 和内存开销。
- 兼容性:DEX 文件是平台无关的,而机器码是平台相关的,转换过程确保了应用可以在不同设备上高效运行。
通过这种方式,Android 系统能够在保证兼容性的同时,最大限度地提升应用性能。
明天再详细了解一下什么是机器码