Dalvik虚拟机作为Android平台的核心组成部分之一,允许在有限的内存资源中同时运行多个虚拟机实例。Dalvik虚拟机通过以下方式提升性能:
1、DEX代码安装时或第一次动态加载时odex化处理。
2、Android2.2版本提供了JIT机制提升性能,号称性能提升3~5倍。
3、提升硬件配置,如更多核CPU、更高频率CPU、更大的RAM等。
但是Android的系统流畅度与IOS系统还是有一定得差距。Android代码必须运行在Dalvik虚拟机上,而IOS直接是本地代码,性能差距也在情理之中。如果Android系统想拥有与IOS系统相同的系统性能。Dalvik虚拟机运行机制就成为Android系统性能提升唯一的障碍。
Android Kitkat 提供了一种与Dalvik截然不同的运行环境-ART(Android Runtime)的支持。目前用户可以选择设备的运行环境,在不久的将来ART肯定会替代Dalvik Runtime。
二、Dalvik vs ART
Dalvik运行环境使用JIT(Just-In-Time)来进行转译,应用每次运行的时候,字节码都需要通过JIT转换为机器码,这会拖慢应用的运行效率。而ART则是使用AOT进行处理(Ahead-Of-Time),并会在应用程序安装完毕时,进行预先的基础性编译作业,这就减去了JIT运行时的机器码转化时间,应用的启动和执行都会变得更加快速。
ART优点:
1、系统性能的显著提升。
2、应用启动更快、运行更快、体验更流畅、触感反馈更及时。
3、更长的电池续航能力。
4、支持更低的硬件。
ART缺点:
1、更大的存储空间占用,可能会增加10%-20%。
2、更长的应用安装时间。
总的来说ART的功效就是“空间换时间”。
三、初步感知ART
1、设备如何选择ART运行环境
通过以下步骤开启:设置→关于手机→点击最下面的版本号7次→开发者模式出现→返回→进入开发者模式,然后选择runtime-使用ART
目前官方Android模拟器并不能开启ART模式,可以通过该网址下载支持ART模式的Android模拟器镜像 ( https://blog.****.net/coolypf/article/details/17069015)
2、Dalvik切换ART后系统变化
2.1、应用安装时采用的代码优化方式不同:
Dalvik Runtime : dex2opt(https://124.16.139.131:24080/lxr/source/dalvik/dexopt/OptMain.cpp?v=android-4.0.4#f_OptMain.cpp)
ART Runtime : dex2oat (https://android.googlesource.com/platform/art/+/kitkat-release/dex2oat/dex2oat.cc)
2.2、优化后的文件大小及格式不同:
两个运行环境产生的优化代码路径及文件名都为:/data/dalvik-cache/app/[email protected]@{package name}[email protected]
ART环境产生的优化代码文件大小明显比Dalvik环境产生大:
虽然都为.dex文件结尾,但是文件格式却是天壤之别:
ART环境文件格式:ELF Shared Object
Dalvik环境文件格式:
三、ART相关源代码
ART相关源代码下载地址:(https://android.googlesource.com/platform/art/+archive/kitkat-release.tar.gz)
从源代码文件目录名称可以很清楚的了解各文件夹中相关文件的功能,我们最关心的主要有compiler、dex2oat、runtime三个文件夹:
compiler:主要负责Dalvik字节码到本地代码的转换,编译为libart-compiler.so
dex2oat :完成DEX文件到ELF文件转换。编译为dex2oat
runtime :Android ART运行时源代码,编译为libart.so
四、dex2oat优化流程
在应用安装时,installd通过dex2oat优化APK安装包classes.dex的Dalvik字节码为本地机器代码。整个优化为:
更多LLVM编译器的信息可查看:
https://llvm.org/
https://www.ibm.com/developerworks/cn/opensource/os-createcompilerllvm1/
https://www.chinaicexpo.com/market/1104-llvm.html
五、OAT文件格式
OAT文件其实就是基于ELF格式的一种私有文件格式。
OAT的ELF 段信息:
OAT的ELF export信息:
OAT文件加载流程,通过分析ART相关源码,当通过DexClassLoader加载一个OAT文件基本流程如下:
1、读取oatdata符号地址获取Oat数据 startAddress。
2、读取oatlastword符号地址获取OAT数据 endAddress。
3、通过startAddress和endAddress定位Oat数据。
4、解析Oat数据。构建方法定位所需数据结构。
然后就可以调用加载OAT文件的代码了。
整个的方法定位过程和Dalvik运行环境没有太大区别,读者可以通过(https://blog.****.net/androidsecurity/article/details/8664778)来了解如何定位到一个类的某个方法。
您可以简单的认为ART和Dalvik区别就是:Dalvik定位到的方法是Davlik字节码,但是ART定位到的方法是本地代码。仅是方法代码内容发生了变化,但是方法的定位过程基本相同。
我们以关键的地址点为分割截取OAT文件数据段:
ELF头:
OAT数据内容开始:(注意0x10BB位置,DexHeader开始)
可执行本地代码部分:
OAT数据结束位置:
具体的OAT文件格式可以查看源代码。