从JVM到Dalivk再到ART(class,dex,odex,ELF)

个人博客地址 http://dandanlove.com/

现在市面上的Android手机大部分都是运行的是ART虚拟机了。还记得自己一部Android手机(HUWEIg520),Android4.1系统。那时候还是没有ART虚拟机的。作为Android开发者,我们应该对Android的发展历史有些了解为什么Android会经历这么多的变化。Android是先有JVM然后是Dalvik,接着是现在的ART虚拟机。那么他们之间有什么关系呢?

JVM就不用讲述了大家都有了解,不了解的参见JVM百度百科

Dalvik是Google公司自己设计用于Android平台的虚拟机,是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。它可以支持已转换为 .dex格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。

Dalvik和JVM的主要区别

首先通过介绍Dalvik的时候我们就知道Dalvik运行的是dex文件,而JVM运行的是class文件。

Dalvik VM是基于寄存器的架构,而JVM是栈机。所以Dalvik VM的好处是可以做到更好的提前优化(ahead-of-time optimization)。 另外基于寄存器架构的VM执行起来更快,但是代价是更大的代码长度。
~~
基于寄存器架构的虚拟机有这么多的好处,为什么之前设计JAVA的程序员没有采用呢,而是采用现在基于栈的架构开发的呢?因为基于栈的虚拟机也有它的优点,它不对host平台的寄存器数量做假设,有利于移植到不懂的平台,这也符合的Java跨平台的特点。而Dalvik虚拟机则不关心这些,因为它本来就是为ARM这样的多寄存器平台设计的,另外Dalvik被移植到x86机器上,即使x86这种寄存器少的平台,寄存器架构的虚拟机也可以运行。
~~
一般来说,基于堆栈的机器必须使用指令才能从堆栈上的加载和操作数据,因此,相对基于寄存器的机器,它们需要更多的指令才能实现相同的性能。但是基于寄存器机器上的指令必须经过编码,因此,它们的指令往往更大。

public class Demo {
    public static void foo() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 5;
     } 
}

我们可以查看Demo.java在JVM中的class和Dalvik的dex字节码文件:
详见:使用dx将class转dex总结

想要了解更多:基于栈的虚拟机 VS 基于寄存器的虚拟机

Dalvik在JVM上的优化

  • 在编译时提前优化代码而不是等到运行时
  • 虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。
  • 常量池已被修改为只使用32位的索引,以简化解释器
  • 标准Java字节码实行8位堆栈指令,Dalvik使用16位指令集直接作用于局部变量。局部变量通常来自4位的“虚拟寄存器”区。这样减少了Dalvik的指令计数,提高了翻译速度。

在这里插入图片描述

Dalivk进化之ART

2014年6月25日,Android L 正式亮相于召开的谷歌I/O大会,Android L 改动幅度较大,谷歌将直接删除Dalvik,代替它的是传闻已久的ART。

ART:即Android Runtime
ART 的机制与 Dalvik 不同。在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。

ART的优缺点

优点:

  • 系统性能的显著提升。
  • 应用启动更快、运行更快、体验更流畅、触感反馈更及时。
  • 更长的电池续航能力。
  • 支持更低的硬件。

缺点:

  • 机器码占用的存储空间更大,字节码变为机器码之后,可能会增加10%-20%(不过在应用包中,可执行的代码常常只是一部分。比如最新的 Google+ APK 是 28.3 MB,但是代码只有 6.9 MB。)
  • 应用的安装时间会变长。

class、dex、odex、ELF相爱相杀

从执行文件上面进行分析的话,JVM对应class文件,Dalivk对应odex文件,而ART对应dex文件。

为了在JVM优化出一个Dalivk虚拟机,所以把JVM运行的class文件进行打包优化为dex文件,但其本质还是和class文件一样属于字节码文件。但是为了每次启动时都去掉从字节码到机器码的编译过程,Google又从Dalivk中优化出了ART,在其安装应用的时候将dex文件进行预处理生成可执行的oat文件。

JIT的引入

据说Android 2.2的虚拟机dalvik使用了JIT技术,使其运行速度快了5倍。dalvik解释并执行程序,JIT技术主要是对多次运行的代码进行编译,当再次调用时使用编译之后的机器码,而不是每次都解释,以节约时间。5倍是测试程序测出的值,并不是说程序运行速度也能达到5倍,这是因为测试程序有很多的重复调用和循环,而一般程序主要是顺序执行的,而且它是一边运行,一边编译,一开始的时候提速不多,所以真正运行程序速度提高不是特别明显。

每启动一个应用程序,都会相应地启动一个dalvik虚拟机,启动时会建立JIT线程,一直在后台运行。当某段代码被调用时,虚拟机会判断它是否需要编译成机器码,如果需要,就做一个标记,JIT线程不断判断此标记,如果发现被设定就把它编译成机器码,并将其机器码地址及相关信息放入entry table中,下次执行到此就跳到机器码段执行,而不再解释执行,从而提高速度。

Odex

因为apk实际为zip压缩包,虚拟机每次加载都需要从apk中读取classes.dex文件,这样会耗费很多的时间,而如果采用了odex方式优化的dex文件,他包含了加载dex必须的依赖库文件列表,只需要直接加载而不需要再去解析。

AOT(Ahead-of-time)

ART 推出了预先 (AOT) 编译,可提高应用的性能。ART 还具有比 Dalvik 更严格的安装时验证。在安装时,ART 使用设备自带的 dex2oat 工具来编译应用。该实用工具接受 DEX 文件作为输入,并针对目标设备生成已编译应用的可执行文件。之后打开App的时候,不需要额外的翻译工作,直接使用本地机器码运行,因此运行速度提高。

ELF文件

ELF(Executable and Linking Format)是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东西、以及都以什么样的格式去放这些东西。它自最早在 System V 系统上出现后,被 xNIX 世界所广泛接受,作为缺省的二进制文件格式来使用。可以说,ELF是构成众多xNIX系统的基础之一。

文中部分内容摘自:
深入理解JVM-字节码执行引擎
Android 中的Dalvik和ART是什么,有啥区别?
知乎-Dalvik 虚拟机和 Sun JVM 在架构和执行方面有什么本质区别?
《Java虚拟机原理图解》4.JVM机器指令集

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦

想阅读作者的更多文章,可以查看我 个人博客 和公共号:
振兴书城

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章