虚拟机的执行方式 | 青训营笔记

195 阅读5分钟

这是我参与「第四届青训营 」笔记创作活动的第14天

虚拟机

Android虚拟机有两种:DalvikART,JIT与AOT是虚拟机为了提高运行效率等采用的不同的编译策略(程序运行方式)。

  • Dalvik,在Android 5.0版本前居多
  • ART,, 在Android 5.0版本后正式全面引进

更多详解请见ART | 青训营笔记 - 掘金 (juejin.cn)

执行方式

image.png

解释执行

   ~~~ 由解释器根据输入的数据当场执行而不生成任何目标程序。
   ~~~ 解释执行程序是高级语言翻译程序的一种,它将源语言(如VASIC)书写的源程序作为输入,解释一句后就提交给计算机执行一句,并不生成目标程序。这种工作方式非常适合于人通过终端设备与计算机会话,如在终端上打一条命令或者语句,解释程序就立即将此语句解释成一条或几条指令并提交硬件立即执行且将执行结果反映到终端,从终端把命令打入后,就能立即得到计算结果,适合一些小型机的计算问题。

优点

不依赖于平台,因为每次都会根据不同的平台对语句进行解析,像JS就是一种边解释边执行的语言,不管是在windows还是linux都可以直接用

缺点

解析是需要时间的,每次都解析在很多情况下都是相当于每次都在做重复功,这样运行的效率比较低、执行速度很慢,例如源程序中出现循环,则解释程序也重复地解释并提交这一组语句,会造成很大浪费。

JIT

JIT(Just In Time Compiler):即时编译技术,与Dalvik虚拟机相关,运行时编译,属于动态编译。

image.png 原理: 将解释过的机器码缓存起来,下次再执行时到这个方法的时候,则直接从缓存里面取出机器码来执行,减少了读取字节码和翻译字节码的操作,以此来提高效率。JIT技术的引入使得 Dalvik 的性能提升了3~6倍
注意: 并不是所有执行过的代码对应的机器码都会被缓存起来。而是只有被认定为热点代码(Hot Spot Code) 的代码才会。
热点代码包括:
1、被多次调用的方法
2、多次执行的循环体(虽然只是循环体被多次执行,但仍是将整个方法的机器码缓存起来)\

缺点

1、每次重新启动引用都需要重新编译
2、运行时比较耗电

AOT/OAT

AOT(Ahead Of Time):提前编译,程序在执行前全部被翻译为机器码,属于静态编译

原理: 在程序运行之前,对APK中的函数进行编译。具体来说就是,提前将字节码转换成本地机器码,然后存储在本地磁盘上,运行时可以直接执行,避免了Dalvik时期的应用运行时再来解释字节码,运行时效率大大提高。

  • 和程序是否运行无关
  • 编译的范围不是以函数为单位,而是以dex为单位的
  • 结果会持久化

混合编译模式

背景

在Android 7.0 之前,Android系统安装应用的时候,会进行一次预编译,将字节码预先编译成本地机器码,生成.oat文件,并存储在本地磁盘上,也就是AOT技术。这样在应用每次运行时就不需要重新编译,可以直接使用编译好本地机器码,运行效率大大提升。但是这也使得安装应用的时间大大增加,于是在Android7.0,又重新引进了JIT技术,形成JIT/AOT混合编译模式。

特点

  • 应用在安装的时候,不进行AOT预编译。
  • 应用运行时直接通过解释器翻译字节码为机器码然后执行(在应用运行期间使用了JIT技术)并同时记录热点代码信息到profile文件中。
  • 手机进入空闲或充电状态的时候,系统会扫描APP目录下的profile文件,并通过AOT对热点代码进行编译。下一次启动时,会根据profile文件来运行已编译好的机器码,避免在运行时对已经变过的方法又进行了JIT编译。
  • 应用运行期间会持续对热点代码进行记录,以方便在空闲或充电时进行AOT,以此循环。
  • 使用了JIT来对AOT进行补充,可以提升运行时性能,节省存储空间,加快应用运行速度。

dex文件

   ~~~ dex是二进制文件,用于在Android虚拟机上执行,是通过把所有的class文件进行合并优化得到的。dex文件去除了class文件中的冗余信息(比如重复字符串),并且结构更加紧凑,因此在dex解析阶段可以减少I/O操作,提高类查找速度。
   ~~~ 它与.jar文件不同,.jar文件像是一个文件夹,里面的.class是单独的文件,各个class信息里面会出现重复的信息。而dex文件,则将所有的.class里面的信息整合在一起,去除掉里面的重复数据。