Dalvik和ART编译方式的演进

简介

ART和Dalvik

Android Runtime (ART) 是 Android 上的应用和部分系统服务使用的托管式运行时。ART 及其前身 Dalvik 最初是专为 Android 项目打造的。作为运行时的 ART 可执行 Dalvik 可执行文件并遵循 Dex 字节码规范。
ART 和 Dalvik 是运行 Dex 字节码的兼容运行时,因此针对 Dalvik 开发的应用也能在 ART 环境中运作。不过,Dalvik 采用的一些技术并不适用于 ART。

JTI和AOT

在 Android 中,Java 类被转换成 DEX 字节码。DEX 字节码通过 ART 或者 Dalvik 转换成机器码。
而DEX 字节码 转换成机器码的编译方式,ART 和 Dalvik是不同的:Dalvik 使用 JIT(Just in time)编译而 ART 使用 AOT(Ahead of time)编译。

Just In Time (JIT)
使用 Dalvik JIT 编译器,每次应用在运行时,它实时的将一部分 Dalvik 字节码翻译成机器码。在程序的执行过程中,更多的代码被被编译并缓存。由于 JIT 只翻译一部分代码,它消耗的更少的内存,占用的更少的物理存储空间。
Ahead Of Time(AOT)
ART 内置了一个 Ahead-of-Time 编译器。在应用的安装期间,他就将 DEX 字节码翻译成机器码并存储在设备的存储器上。这个过程只在将应用安装到设备上时发生。由于不再需要 JIT 编译,代码的执行速度要快得多。

而ART虚拟机在编译方式在7.0之后变成了AOT+JIT混合方式。

为啥要了解

因为Android中的热修复等技术会受到编译方式的影响,导致老的热修复方式失效。具体的影响还没有去看,后期再去整理先插个眼。

演进和区别

Android 4.x(Interpreter + JIT)

原理:平时代码走解释器,但热点trace会执行JIT进行即时编译
优点:占用内存少
缺点:耗电(退出App下次启动还会重复编译),卡顿(JIT编译时)

Android 5.0/5.1/6.0(interpreter + AOT)

原理: 在AOT模式下,App在安装过程时, 就会完成所有编译。
优点: 性能好
缺点: App安装时间长,占用存储空间多。

Android 7.0/7.1的ART引入了全新的Hybrid模式(Interpreter + JIT + AOT)

原理: App在安装时不编译, 所以安装速度快。
在运行App时, 先走解释器, 然后热点函数会被识别,并被JIT进行编译, 存储在jit code cache, 并产生profile文件(记录热点函数信息)。
等手机进入charging和idle状态下, 系统会每隔一段时间扫描App目录下profile文件,并执行AOT编译(Google官方称之为profile-guided compilation)。
不论是jit编译的binary code, 还是AOT编译的binary code, 它们之间的性能差别不大, 因为它们使用同一个optimizing compiler进行编译。
优点: App安装速度快,占用存储少(只编译热点函数)。
缺点: 前几次运行会较慢, 只有用户操作得次数越多,jit 和AOT编译后, 性能才会跟上来。

Android Developer7.0对混合编译的解释:
配置文件指导的 JIT/AOT 编译
在 Android 7.0 中,我们添加了即时 (JIT) 编译器,对 ART 进行代码分析,让它可以在应用运行时持续提升 Android 应用的性能。JIT 编译器对 Android 运行组件当前的 Ahead of Time (AOT) 编译器进行了补充,有助于提升运行时性能,节省存储空间,加快应用更新和系统更新速度。

配置文件指导的编译让 Android 运行组件能够根据应用的实际使用以及设备上的情况管理每个应用的 AOT/JIT 编译。例如,Android 运行组件维护每个应用热方法的配置文件,并且可以预编译和缓存这些方法以实现最佳性能。对于应用的其他部分,在实际使用之前不会进行编译。
除提升应用的关键部分的性能外,配置文件指导的编译还有助于减少整个 RAM 占用,包括关联的二进制文件。此功能对于低内存设备非常尤其重要。
Android 运行组件在管理配置文件指导的编译时,可最大程度降低对设备电池的影响。仅当设备处于空闲状态和充电时才进行编译,从而可以通过提前执行该工作节约时间和省电。

综上,Android 7.0/7.1上的ART是将Android 4.x的JIT和Android 5.x/6.0上的AOT结合,取长补短,从而在performance和battery之间取得某种trade off。

上边的区别引用自-知乎的回答