JIT、AOT、Dalvik、ART概念整理

最近整理了Dalvik、ART、JIT、AOT、混合编译等概念,在此写篇博客记录一下

Dalvik

Dalvik是Google公司自己设计用于Android平台的虚拟机

Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一

它可以支持已转换为 .dex格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统

Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik 应用作为一个独立的Linux 进程执行

独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭

Dalvik是执行的时候编译+运行,安装比较快,开启应用比较慢,应用占用空间小

ART

ART即Android Runtime, ART 的机制与 Dalvik 不同

在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率

而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用

这个过程叫做预编译(AOT,Ahead-Of-Time)

这样的话,应用的启动(首次)和执行都会变得更加快速

对比Dalvik,ART是安装的时候就编译好了,执行的时候直接就可以运行的,安装慢,开启应用快,占用空间大

JIT

JIT,即Just-in-time,动态(即时)编译,边运行边编译

在Android中我们的java代码最终会编译成为dex文件,在4.4以下的版本中由Dalvik虚拟机运行

Dalvik虚拟机可以看做是一个Java VM,他负责解释dex文件为机器码,如果我们不做处理的话,每次执行代码,都需要Dalvik将dex代码翻译为微处理器指令,然后交给系统处理,这样效率不高

为了解决这个问题,Google在2.2版本添加了JIT编译器,当App运行时,每当遇到一个新类,JIT编译器就会对这个类进行编译,经过编译后的代码,会被优化成相当精简的原生型指令码(即native code),这样在下次执行到相同逻辑的时候,速度就会更快

当然使用JIT也不一定加快执行速度,如果大部分代码的执行次数很少,那么编译花费的时间不一定少于执行dex的时间。Google当然也知道这一点,所以JIT不对所有dex代码进行编译,而是只编译执行次数较多的dex为本地机器码

有一点需要注意,那就是dex字节码翻译成本地机器码是发生在应用程序的运行过程中的,并且应用程序每一次重新运行的时候,都要做重做这个翻译工作,所以这个工作并不是一劳永逸,每次重新打开App,都需要JIT编译

另外,Dalvik虚拟机从Android一出生一直活到4.4版本,而JIT在Android刚发布的时候并不存在,在2.2之后才被添加到Dalvik中

AOT

AOT是”Ahead Of Time”的缩写,指的就是ART(Anroid RunTime)这种运行方式

前面介绍过,JIT是运行时编译,这样可以对执行次数频繁的dex代码进行编译和优化,减少以后使用时的翻译时间,虽然可以加快Dalvik运行速度,但是还是有弊病,那就是将dex翻译为本地机器码也要占用时间,所以Google在4.4之后推出了ART,用来替换Dalvik

在4.4版本上,两种运行时环境共存,可以相互切换,但是在5.0+,Dalvik虚拟机则被彻底的丢弃,全部采用ART

ART的策略与Dalvik不同,在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。之后打开App的时候,不需要额外的翻译工作,直接使用本地机器码运行,因此运行速度提高

当然ART与Dalvik相比,还是有缺点的

ART需要应用程序在安装时,就把程序代码转换成机器语言,所以这会消耗掉更多的存储空间,但消耗掉空间的增幅通常不会超过应用代码包大小的20%

由于有了一个转码的过程,所以应用安装时间难免会延长

混合编译

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

Android N 包含了一个混合模式的运行时,应用在安装时不做编译,而是解释字节码,所以可以快速启动。ART 中有一种新的、更快的解释器,通过一种新的 JIT 完成,但是这种 JIT 的信息不是持久化的

取而代之的是,代码在执行期间被分析,分析结果保存起来。然后,当设备空转和充电的时候,ART 会执行针对“热代码”进行的基于分析的编译,其他代码不做编译

为了得到更优的代码,ART 采用了几种技巧包括深度内联

对同一个应用可以编译数次,或者找到变“热”的代码路径或者对已经编译的代码进行新的优化,这取决于分析器在随后的执行中的分析数据

这个步骤仍被简称为 AOT,可以理解为“全时段的编译”(All-Of-the-Time compilation)

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

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