😀
主要记录Android Dalvik和ART虚拟机相关的概念、历史、发展、对比。

关键概念

  • Dalvik
    • Android早期使用的虚拟机(Android 5.0之前),使用JIT编译方案。
    • 文件格式dex
  • ART:Android runtime
    • 现在普遍使用的虚拟机(Android5.0及之后),使用AOT编译方案。
    • Android7.0之后,采用AOT\JIT混合的编译方案。
  • JIT:Just In Time
    • 程序运行时,实时将字节码编译为机器代码并执行。
  • AOT:Ahead Of Time
    • 在软件安装的时候就把字节码码编译成机器代码。
  • DEX
    • 专为Android平台设计的一种压缩的执行格式。
    • DEX文件在应用的构建过程中产生。
  • OAT
    • 在ART环境中使用的编译后的执行文件格式,包含了从DEX文件预编译的本地机器代码。

两种虚拟机

Dalvik虚拟机

简介

  • Android的首个版本就开始使用的虚拟机,即2008年发布的Android 1.0。
  • Dalvik是专门为Android系统设计的虚拟机。
  • 主要是为了优化电池续航和提升在有限内存的设备上的运行效率。

特点

  • 基于寄存器
    • Dalvik虚拟机是一个基于寄存器的虚拟机。
    • 相比基于栈的虚拟机(JVM),基于寄存器的设计可以减少指令的数量,从而提高执行效率。
  • JIT编译
    • Dalvik在Android 2.2 (Froyo) 引入了即时编译(JIT),允许应用运行时将频繁执行的代码部分编译成本地代码,这样可以提高应用的执行速度。

Android Runtime (ART)

简介

  • 引入:ART首次引入是在Android 4.4 (KitKat) 。
  • 夺权:在Android 5.0 (Lollipop) 中,ART取代了Dalvik,成为了默认的运行环境。
  • 回归:在Android 7.0(Nougat),JIT 编译器回归,形成 AOT/JIT 混合编译模式。
  • 目的:为了进一步提升应用的性能、减少应用启动时间和系统占用。

特点

  • AOT编译
    • 与Dalvik的JIT编译不同,ART采用了提前编译(AOT,Ahead-of-Time Compilation)。
    • 在应用安装时,ART将全部字节码转换成机器码,这一过程增加了应用的安装时间,但显著减少了运行时的CPU负载和启动时间。
  • 改进的垃圾回收
    • 大多采用并发设计,只有一次 GC 暂停(Dalvik 需要两次)。
    • 并发复制,可减少后台内存使用和碎片
    • GC 暂停的时间不受堆大小影响
    • 在清理最近分配的短时对象这种特殊情况中,回收器的总 GC 时间更短
  • 更好的内存分配和管理
    • ART使用了更加高效的内存分配策略,提高了性能并减少了内存浪费。

作用流程

notion image

编译方案

JIT

  • 引入原因:
    • 在Android 2.2 (Froyo) 之前,Dalvik虚拟机完全依赖于解释执行字节码,这意味着每次运行程序时都需要读取并解释字节码,这会导致性能的下降。
  • 特点:
    • 动态编译:应用代码在运行时根据需要被编译成机器语言。
    • 热点代码优化:JIT编译可以在应用运行时将经常执行的字节码部分(热点代码)编译成本地代码,从而减少解释执行的开销,以提高应用的运行速度。

AOT

  • 引入原因:
    • 为了提高应用的性能,尤其是在应用启动时。通过提前编译,应用可以更快地启动并运行,改善用户体验。
  • 特点:
    • 启动性能:由于代码已经被编译成机器语言,应用程序在启动时无需等待编译,从而减少了启动时间。
    • 运行开销:运行时无需进行额外的编译,因此可以减少CPU的使用和电池消耗。
    • 安装、存储开销:增加应用的安装时间和生成的可执行文件大小。

DEX和OAT

DEX文件(Dalvik Executable)

定义

  • 是Android应用程序中使用的一种压缩的执行格式,专为Android平台设计。

生成时机及过程

  • 时机
    • 应用的编译阶段生成的。
  • 过程:
    • 首先将Java源代码编译成Java字节码(即.class文件)。
    • 然后使用Android SDK中的“dx”工具(或Android Studio内置的构建工具)将.class文件转换成一个或多个DEX文件。
    • 将生成的DEX文件打包进APK中。

作用阶段

  • 对于Dalvik虚拟机,DEX文件在应用运行时被加载,通过解释执行或JIT编译执行。
  • 对于ART虚拟机,DEX文件在应用安装时被预编译成OAT格式。

OAT文件(Android Runtime Executable)

定义

  • 是在ART环境中使用的编译后的执行文件格式,包含了从DEX文件预编译的本地机器代码。
  • 包含的机器代码是针对设备优化过的。

生成时机及过程

  • 时机:应用安装过程中生成的。
  • 过程:
    • 当应用安装时,ART虚拟机会在首次安装期间将DEX文件编译成OAT文件。

作用阶段

  • 应用启动和运行阶段起作用。

特点

  • 由于OAT文件包含预编译的本地代码,它允许ART虚拟机直接执行这些代码,无需在运行时进行任何额外编译,从而提高应用的性能和响应速度。

对比总结

虚拟机对比

Dalvik 虚拟机
Android Runtime (ART)
编译方式
JIT(即时编译)
AOT(提前编译),从Android 6.0起结合JIT
优势
内存和存储占用较低
只有一次 GC 暂停
应用安装时间短
支持更好的垃圾回收机制
缺陷
运行时性能不及ART
安装应用时需要更多时间
随着应用复杂度增加,性能劣势更明显
占用更多的存储空间
引入时间
Android 1.0 (2008)
Android 4.4 (KitKat) 作为实验性选择
Android 5.0被ART取代
Android 5.0 (Lollipop) 正式默认虚拟机
目的
为低性能硬件优化,提高电池续航
进一步提升应用性能,优化用户体验
基本原理
基于寄存器,减少指令数量
全部字节码转换成机器码,优化执行速度
优化内存管理和应用响应速度

编译方案对比

AOT编译
JIT编译
编译时机
在应用安装时完成编译
在应用运行时进行编译
优势
提升应用的启动速度
不需要在安装时进行大量编译
减少应用运行时的CPU和内存负担
节省存储空间,因为不需存储大量编译后的代码
更稳定的性能,因为编译是提前完成的
可以针对用户的使用模式进行优化
能够适应不同硬件和运行时条件
劣势
增加应用的安装时间
可能导致应用初次启动时性能较低
占用更多的存储空间,因为编译的代码会被存储
需要不断编译,增加运行时CPU的负担
性能波动,因为编译发生在运行时
适用场景
性能敏感型应用
开发阶段和测试阶段,迭代快的应用
需要快速启动的应用
资源受限的设备
复杂度
需要复杂的编译器技术,能分析和优化整个应用
较为简单,实时根据应用行为作出编译决策

AOT和JIT对比

AOT编译
JIT编译
编译时机
应用安装前,全部代码一次性编译
应用运行时,根据需要编译
优点
提高应用启动速度,运行时性能稳定
节省空间,适应性强,优化应用运行性能(相对于没有引入JIT而言)
缺点
增大文件大小,延长应用安装时间
初次运行慢,运行时CPU和内存使用可能增加
主要用途
性能敏感应用,需要快速响应的场景
开发和测试阶段,资源受限的设备

DEX和OAT对比

DEX 文件
OAT 文件
定义
Dalvik Executable 文件,包含编译后的Java类的字节码。
Android Runtime Executable 文件,包含可以直接运行的本地机器代码。
文件格式
.dex
.oat
产生时机
在应用打包阶段,将.class文件转换为.dex文件。
在应用安装阶段,ART将.dex文件编译成.oat文件。
作用
在Dalvik虚拟机中,用于运行时解释执行或JIT编译。
在ART虚拟机中,用于提供已经编译和优化的代码,直接执行以提高性能。
性能
解释执行或JIT编译可能导致性能波动。
由于代码已预编译,提供更快的执行速度和更短的启动时间。
优化级别
较低,因为DEX主要依赖虚拟机在运行时的解释或即时编译。
较高,OAT文件在安装时已针对具体硬件进行优化。
存储与安装
文件体积相对较小。
文件体积较大,因为包含了为设备优化后的完整机器代码。
兼容性
主要用于旧的Android系统和Dalvik虚拟机。
专为Android Runtime(ART)设计,用于现代Android系统。

参考/资料

Overleaf自部署Shell学习记录
Loading...