5、编译:aapt&d8&r8&dex

90 阅读3分钟

继续填。

我也不知道记忆里面的东西还是不是最新的了,当时立下这个话题的时候,还是在想对于比较专的高级工程师应该怎么进行考核,主要是考察apk打包的过程的几个重要的流程。

面试的时候我大概会问,请介绍一下android的apk打包过程。

那我们就慢慢聊一下:

  1. aapt是处理资源的,主要任务生成R.java文件,同时打包出.arsc资源包文件,这个任务比编译任务javac和kotlinc还要早,为什么?因为R.java文件需要参与到整个编译流程中。在包体积极限优化的过程中,会针对.arsc文件进行变体删减,从而删减文件段占用。
  2. d8是处理脱糖的,desugaring。这个怎么理解?众所周知,dalvik是对jvm进行优化调整的,最重要的调整是基于寄存器和字节码的裁剪,so Java Android != Java SE。为了能在dalvik机器上跑通java7、java8引入的新特性,新语言特性,不得不在编译过程中加入一道脱糖过程,将将在语法层面一些底层字节码不支持的特性转换为基础的字节码结构,譬如lambda表达式、方法引用、默认接口方法。d8为了新特性兼容,方便兼容ide的高版本java编写习惯,非常值得。当工程已经使用java8+版本时,一定要开启d8特性。
  3. r8是为了替换proguard的工具,proguard是一个公开的项目,在java项目中应用广泛,它的母公司(Guard Square)也有商用的版本提供。在r8之前,android一直都是d8+proguard的方式进行代码混淆的。
  4. 上述d8和r8之后,就是产出.dex文件,也就是android编译好的代码文件。而d8和r8的关系并不是2个任务,其实是同一个编译任务,输入的是.class文件,输出的是.dex文件,r8的前序任务就是d8,也可以说r8任务包含d8任务。d8和r8比较显眼的成效就是编译速度提升,进一步优化字节编码,执行效率更高,压缩.dex文件的占用大小。

简单交代一下前序任务包括javac、kotlinc、aidl编译等;后序任务包括apkbuilder将所有产物打包成apk,然后进行zipalign和apksigner等;

这个面试问题也是触达一下候选人对具体的apk构成,打包编译过程以及相关变体配置等细节项目的了解。考察的是候选人知识的广度,是否是有主动探索细节的兴趣爱好。因为每一个过程的细节都是值得细细追问。

  • 脱糖的语法你知道的有哪些啊?
  • 你知道的哪些开源库会在aapt上进行改造?
  • arsc文件的具体构成是怎样的?dex文件的具体构成是怎么样的?
  • 如何解决.dex文件方法超限的问题?
  • 怎么指定0.dex文件包括哪些.class?
  • 怎么提升gradle打包编译速度?
  • 请展开说一下泛型/lambda表达式脱糖的过程?
  • 你能比较一下r8和proguard两个工具吗?

这些工具细节很有趣,感兴趣的同学可以了解一下具体的内容。工具其实并不比源码更简单。 有兴趣的同学可以自行试试编译一个java类,javac编译成class,dx编译成dex,放到android手机上面通过dalvik命令运行一下。其过程和java -jar运行一个代码差不多的。