2008年9月22日,谷歌正式对外发布第一款Android手机——HTCG1。9月23日,谷歌发布。在此后的10多年时间内,Android系统不断迭代更新,至此已经来到了Android10时代,其Android虚拟机也变得不断成熟和高效。
早期Android虚拟机在Android系统初期,不同于Java平台使用JVM加载字节码文件(.class文件),Android系统由Dalvik担任虚拟机的角色。.dex文件是Dalvik虚拟机的可执行文件,每次运行程序的时候,Dalvik负责加载dex/odex文件并解析成机器码交由系统调用。
——JIT首次登场为了适应硬件速度的提升,Android系统系统也在不断更新,单一的Dalvik虚拟机已经渐渐地满足系统的要求了,2010年5月20日,Google发布(Froyo冻酸奶),在这个版本中,Google在Android虚拟中加入了JIT编译器(Just-In-TimeCompiler)。
和其他大多数JVM一样,Dalvik使用JIT进行即时编译,借助JavaHotSpotVM,JIT编译器可以对执行次数频繁的dex/odex代码进行编译与优化,将dex/odex中的DalvikCode(Smali指令集)翻译成相当精简的NativeCode去执行,JIT的引入使得Dalvik的性能提升了3~6倍。
但是JIT模式的缺点也不容忽视:
每次启动应用都需要重新编译
运行时比较耗电,造成电池额外的开销
——ART和Dalvik并存2013年9月,Google发布(Kitkat),带来了全新的虚拟机运行环境ART(AndroidRunTime)的预览版和全新的编译策略AOT(AheadofTime),需要注意的是,彼时ART是和Dalvik共存的,除了默认的Dalvik模式,还支持ART模式。用户可以在两者之间进行选择。
——ART全面取代Dalvik2014年10月,Google发布(Lollipop),ART全面取代Dalvik成为Android虚拟机运行环境,至此,Dalvik退出历史舞台,AOT也成为唯一的编译模式。
AOT和JIT的不同之处在于:JIT是在运行时进行编译,是动态编译,并且每次运行程序的时候都需要对odex重新进行编译;而AOT是静态编译,应用在安装的时候会启动dex2oat过程把dex预编译成ELF文件,每次运行程序的时候不用重新编译,是真正意义上的本地应用。
——JIT回归用过Android手机的人应该都知道,在和6.x的机器上,系统每次OTA升级完成重启的时候都会有个应用优化的过程,这个过程就是刚才所说的dex2oat过程,这个过程比较耗时并且会占用额外的存储空间。
2016年8月,Google发布(Nougat),JIT编译器回归,形成AOT/JIT混合编译模式,这种混合编译模式的特点是:
应用在安装的时候dex不会被编译
应用在运行时dex文件先通过解析器后会被直接执行(这一步骤跟之前的行为一致),与此同时,热点函数(HotCode)会被识别并被JIT编译后存储在jitcodecache中并生成profile文件以记录热点函数的信息。
手机进入IDLE(空闲)或者Charging(充电)状态的时候,系统会扫描App目录下的profile文件并执行AOT过程进行编译。
混合编译模式综合了AOT和JIT的各种优点,使得应用在安装速度加快的同时,运行速度、存储空间和耗电量等指标都得到了优化。
结语
Android系统从从诞生到现在,系统经历了多次重大更新,Android虚拟机也在不断进化,如今的混合编译模式是综合了多方面的考虑,在时间、空间和性能之间找到了一个平衡点。相信随着硬件性能的提升和软件架构的发展,谷歌变革的脚步不会停止,优秀的下一代Android虚拟机也许马上就会到来。





