查看原文
其他

了解一下,Android 10中的ART虚拟机(I)

阿拉神农 神农和朋友们的杂文集 2021-11-05

缘起

从今天开始,对Android 10中的ART进行“了解一下”之旅。我本来以为一篇就能拿下,但谁想谷歌从8.0开始对ART进行了更细致和难度更高的改进。粗看了几遍代码,我觉得谷歌不管怎么样还是非常值得国内大厂的学习。改进了这么多,却很少在公开场合宣传。以至于我们误以为人家没干啥。一看代码,好多不认识的地方,好多重构,改进之处。原来,人家一直在努力,在完善....。


关于AOSP的持续改进,这里先举个例子,以后会讲。Android 10中(应该是2018年9月提交的代码)有一个工具叫view_compiler,就是将我们的布局文件转成java代码。这样,我们在渲染布局的时候就不需要读xml然后再解析它,而是直接运行这段代码就完成了布局(包含其中各种控件的添加之类的)。下面是View Compiler的说明。


以上是view_compiler的说明,README中说这是一个实验性的东西...感兴趣的同学可以试一下。权当新年福利。


回到本文,ART目前可能是AOSP中除了kernel外功能最复杂的模块了。所以分了几部分来专门了解一下Android 10中的ART。这一次我们先看看ART中有哪些工具,分别是干什么用的,涉及哪些知识。我大概列了几个比较关注的工具/子模块,如下所示。你要是都知道的话就厉害了

  • dalvikvm:art/dalvikvm

  • dexdiag、dexlayout:代码都在art/dexlayout

  • dexdump:dalvik/dexdump

  • dex2oat:art/dex2oat。我们的老朋友了。这篇讲不了。需要补充基础知识的话请好好阅读《深入理解Android:Java虚拟机ART》一书。

  • dexlist:art/dexlist

  • dexoptanlayzer:art/dexoptanalyzer

  • oatdump:art/oatdum

  • profman:art/profman

  • dexfuzz:art/tools/dexfuzz

  • dexmaker:external/dexmaker

  • vogar:external/vogar

  • caliper:external/vogar


下面我们对来了解一下这些模块。


了解一下dalvikvm

dalvikvm是java虚拟机程序,注意,它就好像是java程序一样。Android上我们其实最熟悉的java虚拟机程序是app_process,也就是zygote。我看了下app_process和dalvikvm的代码。dalvikvm更纯粹,它不会启动Android那套复杂的东西。所以,我看AOSP源码中dalvikvm主要是用来启动一些java测试jar,和android fwk里的那些包没太大关系,更贴近纯java。


了解一下,dexdiag

dexdiag是手机上可运行的一个程序,我试了下,貌似是dump出某个java进程内存映射的情况。

比如adb shell dexdiag --verbose 3285,结果如下:


dexdiag把3285这个java进程映射的各种文件(各种.oat、.vdex文件)的映射信息展示了出来。但我现在还不确定这个玩意具体有啥用,被谁用到。以后碰到再补上。


了解一下,dexlayout

dexlayout是AOSP对ART虚拟机进一步优化的好东西。下面是它的官方说明:


dexlayout是8.0后引入的,它能根据profile的信息对dex文件里的不同信息进行重排。比如,可能把经常调用的函数挪到一起去。这样可充分利用计算机工作的重要基础原理——局部性原理。为什么会有这个优化呢?我猜测谷歌应该不是拍脑子想出来的,而可能有比较稳准狠的检测手段。这就很体现技术力量了。比如,虽然我们可以设计7nm的芯片,但能设计芯片的软件却大部分是外国产品....。很多公司把绝大部分精力花在用户能看得到的地方,却忽视了工具,检测技术的积淀....


dexlayout在主机上也可以运行。方法如下:

dexlayout -t am中间目录/dex/classes.dex。

运行结果是这样的:


这是我在主机上使用dexlayout工具查看am编译的dex文件的结果。具体咋用的我还没研究,后续可能会补充。


注意,这个图中展示了dex文件的一些内容。我发现其中多了一些我在写ART一书时没有碰到的东西,比如MethodHandleCallSiteId。这两个是什么玩意?


了解一下,dex 039版本

不看不知道,一看吓一跳。我在ART一书里研究的时候,dex文件格式还是037版本。到AOSP 9的时候已经升级到039了。主要改了什么呢?谷歌官方文档还是比较详细的有说明:


以上信息可参考官网,地址为https://source.android.com/devices/tech/dalvik/dex-format。


MethodHandler和CallSiteId其实是java里一个比较高级的功能,涉及到如何让java虚拟机支持动态语言。这个就很厉害了。其结果是,JVM以后会不会跑个诸如javascript这样的语言?


JVM支持这个功能的话,我粗浅的推测这可能会对国产某编译器极具创新的改动有比较大的影响。现在有点担心国产编译器选择这条前无古人后无来者的路是否正确了。Anyway,勇者必胜,试错也是大功劳


关于JVM如何支持动态语言,我找了两个比较典型的资料,各位感兴趣的可以看一下。

  1. https://www.pnfsoftware.com/blog/android-o-and-dex-version-38-new-dalvik-opcodes-to-support-dynamic-invocation/

  2. https://mydailyjava.blogspot.com/2015/03/dismantling-invokedynamic.html


相关内容我也截图给大家解解馋。



上面两个图解释了jvm支持动态语言调用的实现(Method Handles)。感兴趣的童鞋尽快补齐相关基础知识哈。我觉得很有用。里边提到说用这种方式貌似比反射的效率会高点(但是这个方式本意上不是替代反射的....)


了解一下,dexlist

dexlist好像是把dex文件里的方法给列出来。下面是运行的结果示意:


抱歉,这个dexlist啥usage信息都打不出来,简单粗暴得很


了解一下,dexoptanalyzer

dexoptanalyzer是用来判断某个dex文件是否需要优化。以下使用说明。


我在想,这玩意有这么神奇?对一个输入dex文件能判断是否需要哪种优化?我感觉可能是结合了当是否有机器码之类的来综合做判断。我试了几个纯dex文件,返回的都是1(kDex2OatFromScratch,就是需要从头到尾生成机器码


了解一下,profman

profman大家应该不陌生,就是生成性能profile的。然后机器码生成的时候能根据profile做有针对性的生成,而不是一股脑都生成。基于profile的机器码生成有个专业术语,叫Profile Guided Optimization(PGO)。PGO是一个目前比较流行的编译优化手段。Android在这块其实也是跟随了微软、苹果的脚步。


谷歌在提升APP运行速度这块貌似没有搞什么所谓的颠覆性创新,而是把其它公司或领域中常用的,好用的,被实践证明过有效的方法拿来。比如Play Store上就搞了PGO。下面是infoq上关于基于云端的PGO的介绍。想法其实很简单。

https://www.infoq.com/news/2019/04/play-cloud-art-profiling-android/


其实就是把多个人本地生成的profile文件(匿名方式,不涉及个人隐私相关的信息)传到云端,然后其他人从play store上下载app的时候连带一个profile文件也被下载过来。然后,这个新下载的app安装时将根据下载过来的profile生成机器码。在没有云端PGO的时候,需要每个人自己运行这个app一段时间后,积累了一些profile信息后才生成更有针对性的机器码。显然,云端PGO,这个技术手段听起来非常自然。


PGO现在很流行,包括iOS的xcode也支持PGO了。我没记错的话号称能提升10%以上的效率。微软的Visual Studio也支持。并且还有一篇比较好的基础知识文章介绍,地址如下:

https://docs.microsoft.com/en-us/cpp/build/profile-guided-optimizations?view=vs-2019


profman相关的内容以后我想介绍下,我也很好奇里边到底都是啥数据。


了解一下,dexfuzz

dexfuzz是一个很有意思的东西。它其实是一个测试工具。其思想是这样的。jvm很复杂,对吧?所以要做大量的测试。而测试代码如果都是人写的话,难免有考虑不全的地方。dexfuzz的作用就是随机对dex文件做一些修改,这样可以生成生成更多,更少见的测试case

dexfuzz比较好的介绍资料见

https://community.arm.com/developer/tools-software/oss-platforms/b/android-blog/posts/the-art-of-fuzz-testing

上面文章的内容的部分截图如下:


dex文件也不能随便乱改,这样会导致字节码校验(这个校验不是文件md5校验,而是非法操作校验,比如new一个基础类型的对象这种java里根本不存在的操作之类的)通不过去。所以可以改一下跳转的目标之类的地方。通过这种方式测验的jvm更经得起考验


了解一下,dexmaker,vogar,caliper

dexmaker是用来生成dex字节码的。它是linkedin提供的一套API,可以动态直接生成dex字节码文件,这样的话,相当于可以动态添加功能了。我查到的资料看dexmaker主要配合测试使用。


我在国内网站上搜索了下dexmaker的用法,好像有很大一部分是用于做插件化处理。而国外几乎都是配合Mockito。dexmaker的官方说明如下


vogar,caliper也是用来测试的。它和dexmaker有一定关系,因为我看dexmaker的说明文档里提到vogar了。

  • vogar可以做性能测试,可参考https://stackoverflow.com/questions/8220549/simple-benchmark-testing-with-vogar。 这个网页里有比较详细的介绍vogar的用法。

  • caliper:caliper是一个基于vogar的性能测试工具。详情可参考https://github.com/google/caliper/wiki/CaliperOnAndroid


后续的安排

AOSP 10源码撸了大概五天,发现其中有一些需要了解的知识,比如APEX、ART等。接下来会对这些东西做一系列的“了解”。在此也欢迎大家提供一些目标,好让我们的"了解Android 10”系列飞得更远一点。


最后的最后

  • 我期望的结果不是朋友们从我的书、文章、博客后学会了什么知识,干成了什么,而应该是说,神农,我可是踩在你的肩膀上的喔。

  • 关于学习方面的问题,我已经讨论完了。后面这个公众号将对一些基础的技术,新技术做一些学习和分享。也欢迎你的投稿。不过,正如我在公众号“联系方式”里说的那样——郑渊洁在童话大王《智齿》里有一句话令我印象深刻,大意是“我有权保持沉默,但你说的每一句话都可能成为我灵感的源泉”。所以,影响不是单向的,很可能我从你那学到的东西更多。


神农和朋友们的杂文集

长按识别二维码关注我们



: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存