Dalvik和ART编译方式的演进以及Android N混合编译对热修复的影响

简介

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中的热修复等技术会受到编译方式的影响,导致老的热修复方式失效。具体的影响可以看这篇对Tinker热修复的影响,Android N混合编译与对热补丁影响深度解析,Android热修复方案的兼容策略CLASS_ISPREVERIFIED问题,其他的收费的或者是功能比较少的就先不分析了。

演进和区别

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 7.0/7.1/N的其他理解

Android N 引入了一种包含编译、解释和 JIT(Just In Time)的混合运行时,以便在安装时间、内存占用、电池消耗和性能之间获得最好的折衷。

ART 是在 Android KitKat(译者注:Android 4.0)引入并在 Lollipop(译者注:Android 5.0)中设为默认解决方案的主要特性之一,是当时的一种新的运行时。ART 取代了 Dalvik,但是前者与后者仍然保持了字节码级的兼容,因为前者仍在运行 DEX 文件。ART 的主要特征之一就是安装时对应用的 AOT 编译。这种方式的主要优点就是优化产生的本地代码性能更好,执行起来需要更少的电量。劣势在于安装文件所需的空间和时间。在 Lollipop 和 Marshmallow(译者注:Android 6.0)中,大的应用需要数分钟才能安装完。

Android N 开发者预览版包含了一个混合模式的运行时。应用在安装时不做编译,而是解释字节码,所以可以快速启动。ART 中有一种新的、更快的解释器,通过一种新的 JIT 完成,但是这种 JIT 的信息不是持久化的。取而代之的是,代码在执行期间被分析,分析结果保存起来。然后,当设备空转和充电的时候,ART 会执行针对“热代码”进行的基于分析的编译,其他代码不做编译。为了得到更优的代码,ART 采用了几种技巧包括深度内联。

对同一个应用可以编译数次,或者找到变“热”的代码路径或者对已经编译的代码进行新的优化,这取决于分析器在随后的执行中的分析数据。这个步骤仍被简称为 AOT,可以理解为“全时段的编译”(All-Of-the-Time compilation)。

这种混合使用 AOT、解释、JIT 的策略的全部优点如下。

  • 即使是大应用,安装时间也能缩短到几秒
  • 系统升级能更快地安装,因为不再需要优化这一步
  • 应用的内存占用更小,有些情况下可以降低 50%
  • 改善了性能
  • 更低的电池消耗

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

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

猜你喜欢

转载自blog.csdn.net/u011148116/article/details/106791704