Android的绝大多数的应用都是使用JAVA语言写的,CPU只能理解汇编指令,无法直接识别JAVA语言的虚拟机指令;为了让CPU能运行JAVA语言编写的程序,一般有2中方法:
1.使用中间层,负责JAVA代码的执行,然后这个中间层本省编译为CPU能理解的汇编指令,也就是CPU->中间层->JAVA代码。一般称这种模式为【解释执行】。这种方式效率相当低效。
2.直接把JAVA语言翻译成CPU能理解的机器语言。有2中实现方式:
1)AOT(Ahead of time) 在程序运行之前直接把JAVA代码编译为机器语言。
2)JIT(Just in time) 在程序运行起来之后,实时地把JAVA语言编译为机器语言然后执行。
在Android5.0正式采用 ART之前,Android采用的是解释执行+JIT的方式执行JAVA代码。
在Android5.0至Android6.0阶段,Google推出了ART(Android Runtime)来解决之前的JAVA代码执行效率问题。这个阶段采用的是完全AOT模式。这种模式有2个缺点:
1)APK安装速度巨慢。尤其 系统OTA开机会对所有的应用执行AOT操作,这个时候开机速度可能需要很长时间。
2)占用磁盘空间,JAVA代码编译为机器码后体积会急剧膨胀。
到了Android7.0,Google做了很大的改进;这一改进基于“我们使用一个应用的时候,基本上只使用了它一小部分功能,为什么把所有代码全编译呢?因此只编译用户经常用的那部分代码就ok了”这样安装的时候速度比较快,等用户启动的时候系统就能知道哪部分代码经常被执行,把这部分代码编译为机器码,运行起来速度也快。
于是Google又引入了JIT,这个时候的执行模式是AOT+JIT+解释执行。
1)应用安装时不执行AOT编译,安装速度飞快。
2)应用运行起来后,系统收集经常被运行的代码的信息,做2件事情:(1)在必要的时候在运行时直接把JAVA代码编译为机器码(JIT),然后使用机器码执行提高运行效率。 (2)把这个【经常被运行的代码信息保存起来】。
3)设备空闲的时候,系统拿出应用运行时候保存的【热点代码信息】直接把这些代码编译为机器码(AOT)
Android8.0 上改进了解释器,解释模式执行效率大幅提升;Android10.0上提供了预先放置热点代码的方式,应用在安装的时候就能知道常用代码会被提前编译。可以看到,当前Android平台的执行模式在空间占用+安装速度+运行速度上已经到达一个很好的平衡。
总结:目前Android采用的解释执行+还算可以的JIT+AOT的综合模式,但是并没有摆脱这样一个前提:即应用在被打包成APK的时候,采用的还是JAVA代码。换句话说,在APK变成用户可应用的过程中,还经历了一个在Android系统内部的编译过程,这是一个绕不过的坎。