前语

尽管Android程序是运用Java言语开发的,当然,现在也能够运用kotlin言语。可是实际上咱们开发出来的Android程序并不能运转在JVM上,而是只能运转在一个类似JVM的Android虚拟机上。Android虚拟机有两种,分别是Dalvik虚拟机ART虚拟机

Dalvik 虚拟机

Dalvik虚拟机是Google自己设计的用于Android渠道的虚拟机,它曾经是Android渠道的中心组成部分之一。它担任加载dex/odex文件并解析成机器码然后履行。Dalvik虚拟机并没有遵从《Java虚拟机标准》,因此不能算是Java虚拟机。可是它与Java却又有联络,它履行的DEX文件是经过Class文件转化而来。咱们也能够认为它是为了能在安卓设备运转而对JVM进行优化的产品

Dalvik诞生消亡史

  • Android 1.0,运用Dalvik作为Android虚拟机运转环境。
  • Android 2.2,Google在Andriod虚拟机中加入了JIT编译器(Just-In-Time Compiler)。
  • Android 4.4,Google带来了全新的虚拟机运转环境ART,此刻ART和Dalvik是共存的,用户能够在两者之间进行选择。
  • Android 5.0,ART全面替代了Dalvik成为了Android虚拟机运转环境,至此Dalvik退出历史舞台。

Dalvik 特色 (与JVM的区别)

  • Dalvik虚拟机运转的是Dalvik字节码,Dalvik字节码由Java字节码转化而来,并被打包到一个dex文件中。而JVM运转的是class文件或jar文件。
  • 加载速度快,dex相比于Jar文件会把一切包含的信息整合在一起,减少了冗余信息。这样就减少I/O操作,进步类的查找速度。
  • Dalvik虚拟机是根据寄存器,而JVM是根据栈(操作数栈)。尽管根据寄存器履行功率好,可是可移植性差,难跨渠道。
  • Dalvik虚拟机答应在有限的内存中一起运转多个进程,每一个运用都运转在一个Dalvik虚拟机实例中,拥有独立的进程空间。
  • Dalvik虚拟机有同享机制,不同运用之间在运转时能够同享相同的类,拥有更高的功率。

什么是JIT(Just-In-Time Compiler)

前期没有JIT的时分,虚拟机运转时,会经过解说器来解说字节码并将其翻译为机器码,逐条读入,逐条翻译,最后再履行,这样就比较慢,功率不高。针对上面这个问题,引进了JIT(即时编译器)技能。它是一种优化手段

JIT技能简略来说便是将解说过的机器码缓存起来,下次再履行时到这个办法的时分,则直接从缓存里边取出机器码来履行。减少了读取字节码和翻译字节码的操作。以此来进步功率。JIT技能的引入使得Dalvik的性能提高了3~6倍

不过要注意的是并不是一切履行过的代码对应的机器码都会被缓存起来。而是只要被认定为热门代码(Hot Spot Code) 的代码才会。这儿所指的热门代码主要有两类,包含:

  • 被多次调用的办法
  • 被多次履行的循环体(尽管仅仅循环体被多次履行,但仍是将整个办法的机器码缓存起来)

JIT技能虽好,可是也是有缺点的:

  • 每次从头启动引用都需求从头编译
  • 运转时比较耗电

什么是dex

dex是二进制文件,用于在Android虚拟机上履行。是经过把一切的class文件进行合并优化得到的。dex文件去除了class文件中的冗余信息(比如重复字符串),而且结构愈加紧凑,因此在dex解析阶段能够减少I/O操作,进步类查找速度。

它与.jar文件不同,.jar文件像是一个文件夹,里边的.class是独自的文件,各个class信息里边会出现重复的信息。而dex文件,则将一切的.class里边的信息整合在一起,去除去里边的重复数据。

Android虚拟机Dalvik和ART

什么是odex

odex是从apk提取出dex文件并经过优化后得到的产品,它被保存到data/dalvik-cache目录下。原apk文件中的classes.dex能够保存也能够删去,乃至有时分会留下残损的dex文件。

体系在初次启动时,需求对预置的apk进行装置,此刻需求将dex从apk文件中解压出来放到data/app文件夹中。

  • 在Dalvik虚拟机中,会经过dexopt来对dex进行优化,生成odex文件,并将其保存到手机的VM缓存文件夹data/dalvik-cache下(注意,这边生成的odex文件后缀依然是dex )。它是一个dey文件,里边依然还是字节码。

  • 在ART虚拟机上,相同会在初次进入体系的时分运用dexopt工具来对dex进行优化,不过此刻的优化是将dex字节码翻译成本地机器码。并保存在data/dalvik-cache下。

一般情况下,在Android体系进行编译的时分,预处理提取Odex文件的话,将会大大优化体系初次启动时刻。

ART 虚拟机

ART虚拟机在Android 5.0开端替换Dalvik虚拟机。其处理运用程序履行的方式不同于Dalvik虚拟机,它不运用JIT而是运用了AOT(Ahead-Of-Time),也便是提早编译技能。而且对废物收集器也进行了改善和优化,当然也还包含了其他的优化。

什么是AOT(Ahead-Of-Time

AOT也便是提早编译技能。简略来说便是提早将字节码转化成本地机器码,然后存储在本地磁盘上,运转时能够直接履行,防止了Dalvik时期的运用运转时再来解说字节码。运转时功率大大进步。

在Android 7.0 之前,Android体系装置运用的时分,会进行一次预编译,将字节码预先编译成本地机器码,生成.oat文件,并存储在本地磁盘上,也便是AOT技能。这样在运用每次运转时就不需求从头编译,能够直接运用编译好本地机器码,运转功率大大提高。可是这也使得装置运用的时刻大大增加,

于是在Android7.0,又从头引进了JIT技能,构成JIT/AOT混合编译形式,这种混合编译的特色是:

  • 运用在装置的时分,不进行AOT预编译。
  • 运用运转时这直接经过解说器翻译字节码为机器码然后履行。并一起记载热门代码信息到profile文件中。
  • 手机进入闲暇或充电状况的时分,体系会扫描APP目录下的profile文件,并经过AOT对热门代码进行编译。
  • 下一次启动时,会根据profile文件来运转已编译好的机器码,防止在运转时对现已变过的办法又进行了JIT编译。
  • 运用运转期间会继续对热门代码进行记载,以方便在闲暇或充电时进行AOT,以此循环。

运用了JIT来对AOT进行补充,能够提高运转时性能,节省存储空间,加快运用运转速度。 具体能够检查google官方文档:实现 ART 即时 (JIT) 编译器

ART废物收集器优化

  • 只要一次GC暂停(Dalvik需求两次)
  • 并发仿制,可减少后台内存运用和碎片
  • GC暂停的时刻不受堆巨细影响
  • 在清理最近分配的短时目标这种特殊情况中,收回器的总GC时刻更短
  • 优化了废物收回的工效,能够愈加及时地进行并行废物收回,这使得GC_FOR_ALLOC事情在典型用例中极为稀有

ART时刻线

  • Android 4.4 ,ART和Dalvik是共存的,用户能够在两者之间进行选择。
  • Android 5.0,正式替代Dalvik虚拟机成为Android虚拟机运转环境,Dalvik退出历史舞台,AOT替代JIT。
  • Android 7.0,JIT回归,选用JIT和AOP混合编译形式。
  • ART继续更新优化

Dalvik VM 和 ART VM 有什么区别

  • ART前期运用AOT技能,后期运用AOT+JIT混合,而Dalvik运用JIT
  • ART支撑64位CPU并兼容32位CPU,而Dalvik只支撑32位CPU
  • ART对废物收集器进行了改善优化,进步了吞吐量。

参考

Android Runtime (ART) 和 Dalvik