Android Runtime 的简单了解

一 什么是Android Runtime

Android Runtime是Android系统里面的核心模块之一。在编译Android代码后会生成APK文件,如果我们打开APK文件,会发现.dex后缀的文件,这些文件包含了了我们APP运行的所有源码,它们的表现形式为—— 字节码(byte code)。而字节码是无法直接被机器执行的,所以Android Runtime的作用是将.dex文件的字节码(byte code)翻译成机器可以直接执行的机器码(machine code)。机器码(machine code)是一系列可以直接被机器理解和CPU执行的指令。当然Android Runtime还有其他包括内存管理,垃圾回收等功能,不是我们今天所要了解的重点。

我们所说的Dalvik和ART则是Google官方对Android Runtime的具体实现,他们分别代表了不同的实现策略。

二 Dalvik、ART、JIT、AOT

APP性能可以分为如上几类,Google所作的一切努力都是为了提升如上所示的指标。

Dalvik虚拟机

早期Android系统Android Runtime的具体实现,直到在Android K发布后,光荣退役。受限于早期智能手机的存储空间和RAM,Dalvik的出现便是为了解决优化一个核心指标——RAM的使用。不同于现在动辄6G,8G的RAM,早期智能手机的RAM最低可以低到200MB。所以为了避免编译整个APP,Dalvik采用了 Just In Time (JIT)的编译策略。

JIT(Just in Time)

JIT的核心原理是编译器仅仅只在APP运行到相关代码的时候才会去编译当前运行的一小部分代码。也正是因为这一原理,Dalvik虚拟机仅仅只在运行时编译他所需要执行的代码,这样就可以节省下大量的RAM。但是我们很快就能想到,这种策略有一个致命的问题,因为一切都发生在运行时,当我们运行时虚拟机才会去编译我们所需要的代码,编译完成后,我们才能执行。这样就会严重影响APP运行时候的性能。虽然Google为Dalvik这种机制做了非常多的优化,比如对一些常用的代码进行缓存,不用频繁编译,但是这些优化手段能够起到的作用非常有限。随着时间的推移,我们的手机性能变得越来越强劲,RAM也变得越来越大,存储空间也越来越大。我们日常所使用的APP,随着功能的增加,也变得越来越大。开发者们开始发现JIT带来的性能影响也越来越大。

Google便在Android L中引入了新的Android Runtime 虚拟机实现——ART

ART虚拟机

ART虚拟机的实现与Dalvik虚拟机的实现是完全不同的。它引入了一种新的编译策略——Ahead of Time(AOT) 而不是继续使用或者优化JIT。

AOT(Ahead of Time)

AOT的核心原理是,在APP安装时便将字节码编译成机器码。这样的实现使得APP在运行时可以直接使用机器码,而不是在运行时再进行翻译,这种方法可以将APP的运行性能提高到使用JIT的20倍甚至更多。但同样的它所带来的问题是 安装APP时间会大大拉长,因为系统需要将字节码翻译成机器码。同时翻译后的产物也会占用更多的存储空间。随着ART的推广,开发者们发现对于一个APP的大部分功能,用户几乎很少使用(二八定律)。所以预编译整个APP,在目前来看是没有必要的,所以Google在Android N中重新引入了 JIT,同时引入了另一种编译策略profile-guide optimization(PGO)。

PGO(Profile-Guide Optimization)

它的原理就是,当ART发现热点代码的时候,这些代码便会被直接翻译成机器码,并被缓存下来。随着执行次数的增加,用户的常用功能被直接探测,那么一个符合用户使用习惯的profile文件便会被生成。用户APP的执行性能也会越来越高。而这一部分的操作也并不是在运行时执行,而是在用户手机空闲的时候根据profile文件做预编译工作。它所带来的缺点就是,系统需要根据用户的使用习惯和方法来进行预编译,也就是说用户在第一次使用的时候只会使用JIT,导致首次使用的性能较差。Google为了解决这种问题在Android P中引入了新的编译策略 profiles in the cloud。具体操作如下所示。

PIC(profiles in the cloud)

它的核心原理是,大部分用户的使用模式趋同,所以对于已经安装了该APP的用户,Google会根据大部分人的行为习惯生成profile文件并存储在云端,所以在新用户安装时,这份文件会随着APK文件同时下发,进行预编译的处理。然后在用户实际使用时,还会不断优化profile文件,进行预编译处理。

三 总结

通过上面的部分,我们可以对文章开头的几个名词有个大概的了解。简单来说,Dalvik和ART是Google对Android Runtime的具体实现。JIT(时间换空间),AOT(空间换时间),PGO(热点代码预编译),PIC(热点代码预测),都是具体的编译策略。不同的编译策略没有好坏之分,他们适用于不同的情况,这也就是为什么Google在移除JIT后,又在后面的版本中重新引入了JIT。

目前来看,国内对于PGO和PIC的讨论并没有多少。PIC本身因为依托于Google商店使得国内的APP厂商兴趣不大。对于PGO,开发者更多的关注于用户的使用性能,用户的使用体验是每个开发团队的核心指标,开发团队希望每个功能的都能让用户直接使用,哪怕是低频功能,而对于涉及到系统整体优化考量的地方则关心不足,任重道远。

参考文献:

JIT的实现

什么是Android Runtime?

深度挖掘ART Runtime

 

posted @ 2021-12-07 18:06  YRLeaner  阅读(2516)  评论(0编辑  收藏  举报