epic原理浅析

Art & Dalvik

Art(Android Runtime)虚拟机是 Android 4.4 发布的,用来替换 Dalvik 虚拟机,但是在Android 4.4 默认采用的还是Dalvik 虚拟机,但是可以选择使用Art。在Android 5.0版本中默认使用Art了,Dalvik退出了历史舞台,所以可以说是在Android在5.0开始正式使用Art虚拟机。

Dalvik中的应用每次运行时,字节码搜需要通过JIT编译器编译成机器码,这会使得应用程序的运行效率降低。而在 ART 中,系统在安装应用程序时会进行一次 AOT(ahead of time compilation, 预编译),将字节码预先编译成机器码并存储在本地,用于生成OAT文件,这个OAT文件既包含转化前的dex文件,又包含机器指令,这样应用程序每次运行时就不需要执行编译了,运行效率会大大提升,设备的耗电量也会降低。不过采用 AOT 也有缺点,主要有两个:第一个是 AOT 会使得应用程序的安装时间变长,尤其是一些复杂的应用;第二个是字节码预先编译成机器码,机器码需要的存储空间会多一些。为了弥补以上两个缺点,Android 7.0 版本的 ART 加入了即时编译器 JIT,引入了混合编译模式,作为 AOT 的一个补充,在应用程序安装时不会将字节码全部编译成机器码,而是在运行中将热点代码编译成机器码,从而缩短了应用程序的安装时间并节省了存储空间。
基本概念和名词

  • .dex文件:App所有java源代码编译后生成众多class文件,由DX/D8,编译为一个/多个(multiDex)dex文件,由Android虚拟机编译执行
  • .odex文件:dex文件经过验证和优化后的产物,art下的odex文件包含经过AOT编译后的代码以及dex的完整内容,但Android8.0之后odex中的dex内容移动到了.vdex文件
  • .art文件:art下根据配置文件生成odex文件时同时生成.art文件,主要是为了提升运行时加载odex中热点代码的速度,包含了类信息和odex中热点方法的索引,运行App时会首先根据这个文件来加载odex中已经编译过的代码
  • 解释器(Interpreter):用于程序运行时对代码进行逐行解释,翻译成对应平台的机器码执行
  • JIT编译(Just In Time):由于解释器方式运行太慢引入,对于频繁运行的热点代码(判定标准一般是在某个时间段内执行次数达到某个阈值)进行实时编译(在ART下以方法为粒度)执行,并且缓存JIT编译后的代码在内存中用于下次执行。由于以方法为粒度(ArtMethod)进行编译,JIT编较于解释器可以生成效率更高的代码,运行更快。
  • AOT编译(Ahead-Of-Time):应用安装时全量编译所有代码为本地机器码,运行时直接执行机器码。

    从这幅图中我们看到:
    在Dalvik虚拟机上,APK中的Dex文件在安装时会被优化成odex文件,在运行时,会被JIT编译器编译成native代码。
    而在ART虚拟机上安装时,Dex文件会直接由dex2oat工具翻译成oat格式的文件,oat文件中既包含了dex文件中原先的内容,也包含了已经编译好的native代码。

    参考资料

    Android上的ART虚拟机
    开源Hook框架-epic-实现浅析