Android虚拟机的JIT编译器

背景

最近参加了华为方舟的Workshop,从编译到Runtime都有了一些体会,并且对于虚拟机的运行也有了一些了解。

Android虚拟机的演变

  • 4.4版本前,使用的是Dalvik虚拟机
  • 5.0版本以后,使用的是Art虚拟机

Dalvik虚拟机

原理
  • Dalvik是基于寄存器的虚拟机,读取和保存数据会比基于栈的JVM在运行时快很多
  • 基于寄存器的虚拟机允许更快的执行时间,但代价是编译后的程序更大
  • 新的Dex字节码格式
    • 合并多个class字节码文件
    • 减少常量池大小
    • 减少文件的IO操作,提高类的查找速度
    • 减少文件大小
  • dex的优化格式odex
    • 在App安装的过程中,会通过Socket向/system/bin/install进程发送dex_opt的指令,对Dex文件进行优化
    • 在DexClassLoader动态加载Dex文件时,也会进行Dex的优化
  • Dalvik的JIT
    • 在运行时对dex的指令进行intercept,解释成机器码
    • 虚拟机根据函数调用的次数,来决定热点代码
    • 函数为维度将热点代码的机器码进行缓存,在下一次调用时直接调用该机器码
KitKat的JIT
优点与缺点
  • 优点
    • 安装速度超快
    • 存储空间小
  • 缺点
    • Multidex加载的时候会非常慢,因为在dex加载时会进行dexopt
    • JIT中需要解释器,解释器解释的字节码会带来CPU和时间的消耗
    • 由于热点代码的Monitor一直在运行,也会带来电量的损耗

5.0-7.0的Art虚拟机

在5.0-7.0(Android N)之间,Android提出了ART虚拟机的概念,而运行的文件格式也从odex转换成了oat格式。

原理

在APK安装的时候,PackageManagerService会调用dex2oat通过静态编译的方式,来将所有的dex文件(包括Multidex)编译oat文件。

编译完后的oat其实是一个标准的ELF文件,只是相对于普通的ELF文件多加了oat data section以及oat exec section这两个段而已。

这两个段里面主要保存了两种信息:

  • Dex的文件信息以及类信息
  • Dex文件编译之后的机器码

在运行的时候,就直接运行oat的代码。而其中的Dex文件的内容也就是为了DexClassLoader在动态加载其他的Dex文件时,在链接的过程中可以找到对应的meta-data,正确的链接到引用的类文件与函数。

罗老师的图
优点与缺点
  • 优点
    • 运行时会超级快
    • 在运行时省电,也节省各种资源
  • 缺点
    • 在系统更新的时候,所有app都需要进行dex2oat的操作,耗费的时间太长
    • 在app安装的过程中,所耗费的时间也越来越长,因为apk包越来越大
    • 由于oat文件中包含dex文件与编译后的Native Code,导致占用空间也越来越大

7.0至今的Art虚拟机

由于上述的缺点,7.0之后的采用了Hybrid Mode的ART虚拟机:

  • 解释器
  • JIT
  • OAT

将这三种方案进行混合编译,来从运行时的性能、存储、安装、加载时间进行平衡。

在第一次启动的时候,系统会以Intercept的方式来运行App,同时启动Compilation Daemon Service在系统空闲的时候会在后台对App进行AOT静态编译,并且会根据JIT运行时所收集的运行时函数调用的信息生成的Profile文件来进行参考 。

而根据Profile生成AOT的过程就是:Profile Guided AOT

而在JIT的过程中会进行以下事情:

  • JIT的解释器:将字节码解释成机器指令
  • JIT的编译器:将函数编译成机器指令
  • 根据运行时的环境生成Profile文件,以供AOT编译时生成机器码
Android N的ART模式
JIT的解释器
  • 对字节码进行解释
    • 基于计算的跳转指令
    • 基于Arm汇编的Operation Code处理
  • Profiling以及JIT编译的触发
    • 基于函数执行次数以及搜索式的代码热度
  • JIT代码缓存
    • 管理编译过的缓存代码
    • 为Hot Methods分配ProfilingInfo对象
JIT的编译器

函数粒度的编译

  • 后台编译
    • 避免Block App的UI线程
  • 基于ART优化的编译器
    • 使用和AOT一样的编译器
  • 在优化编译器中会增强JIT的编译能力
生成Profile文件

使用单独的ProfileSaver线程

  • 生成Profile文件
    • 读取根据Hot Methods生成ProfilingInfo
    • 把ProfilingInfo写到磁盘文件中
  • 最低的消耗
    • 减少Wakeup的次数
    • 写入最少的信息
使用混编模式的原因
  • 部分用户只使用APP的部分功能。而且这些经常使用的功能是值得被编译成Native Code的
  • 使用JIT阶段找出来经常使用的代码
  • 使用AOT编译以及优化来提升经常使用的这些功能
  • 避免为了一些不常用的代码而付出资源(编译、存储等等)
混编模式的实现
  • 在JIT的过程中,生成Offline的Profile
  • Offline Profile的文件格式
  • 使用AOT增强过后的编译器(dex2oat)
  • 编译所使用的Daemon Service
    • 只在充电或者系统IDLE的情况下才会进行AOT编译

Profile文件会在JIT运行的过程中生成:

  • 每个APP都会有自己的Profile文件
  • 保存在App本身的Local Storage中
  • Profile会保存所调用的类以及函数的Index
  • 通过profman工具进行分析生成
Offline Profile

而在BackgroundDexOptService中,会根据JIT运行时所生成的Profile以及Dex文件在后台进行AOT,根据运行时的Profile文件会选择性的将常用的函数编译成NativeCode

Profile Guided AOT

而整个JIT的工作流如下:

工作流

华为的方舟编译器

从方舟编译器来看:

  • 首先会判断该设备支不支持方舟编译器,如果支持,则从应用商店下发方舟版本的包
  • 方舟编译器会把dex文件通过自己的IR翻译方舟格式的机器码,据他们说也是一个ELF文件,但是会增加一些段,猜测是Dex中类信息相关的段
  • 通过这种方式,来消除Java与JNI之间的通信的损耗,以及提升运行时的效率
  • 在方舟内部,还重新完善了GC算法,使得GC的频率大大降低,减少应用卡顿的现象
  • 目前方舟只支持64位的So,并且对于加壳的So会出现一些问题

参考资料

Understanding JIT Compilation and Optimizations
Android profile-guided dex2oat

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容