共计 1544 个字符,预计需要花费 4 分钟才能阅读完成。
编译常见问题
在开发过程中,有碰到过一些因为编译优化导致的代码批改并不合乎咱们预期的状况。这也就是之前为什么我常常说编译产物其实是不太能够被信赖的。
- 办法签名变更,底层仓库的办法变更然而下层模块并没有追随一起从新编译导致的这个问题。
- 常量优化,将一些常量的调用点间接替换成常量的值。
- 删除空导包,没有用的一些导包就会做一次剔除。
最近晦气了
咱们最近碰到一个 pipeline
相干而且很妖怪的问题。咱们一个 pipeline
会查看 apk 产物中是否存在异样的办法调用,就是之前介绍的在 R8 的根底上开发进去的 A8。然而最近有一个类被删除了之后呢,然而代码中还有一处调用点。然而这个检测居然被通过了,而后这部分代码就被合入了 master。
这个援用的文件就如上图所示,是一个 debug buildType
中的,所以并不是所有的 apk 中都会存在这部分代码。
而后呢,这个 MergeRequest
就被合入了 master
分支,因为当天是咱们出下一个版本包的工夫,而后交付给测试的就是全量编译的 debug
和 release
包。别的开发同学 rebase 完 master 之后就发现 piepline
都跑不过了,就导致了他们当天的代码无奈被合入。
这个就是事件大略的起因和通过,然而各位有没有想过为什么会产生这个问题吗。这个是不是咱们的 pipeline
呈现了 bug,导致了这种问题无奈被辨认进去了呢。
以前有说过,如果简略的说咱们的快编零碎就是把模块替换成对应的 aar,从而达到编译提速。所以因为咱们应用的是这个模块对应的 aar 产物,所以大概率就是因为这个模块的编译产物和源代码有差别导致了这个问题。
其实这个问题一呈现我就曾经晓得大概率是由空导包优化导致的这个问题,因为在 pipeline
查看的时候,检测的 apk 产物中的确不存在这个导包。因为咱们应用的是一个历史版本的 aar,其中有效导包的局部曾经被编译器做了删除空导包的优化了。接下来咱们看下我写的一个 demo 中的有效导包。
图一呢是源代码 java 文件,图二呢则是 jar 包中的代码。能够简略的看进去行号呢是能够对应的上的,然而这个 AppCompatActivity
的有效导包在产物中曾经被优化掉了。这里也就答复了在编译过程中会保留行号,然而也会优化掉一部分不须要的代码,让咱们编译进去的产物更小。
所以也就导致了咱们的产物和咱们的源代码之间的差别,另外一个角度就是说从 apk 中咱们的确是不存在这个类的导包。然而呢在咱们把这部分代码从新编译成 aar 的时候,就会呈现 source 缺失,导致的语法树无奈生成,之后导致的编译失败问题。
这也就是所以我始终和大家说编译产物是不能够被信赖的呢。
以前晦气过
这个是之前的一个故事了,咱们之前呢在模块中定义了一些动态常量吧,而后用来标识以后 SDK 的版本,而后这个值在别的模块中被援用到了。
有一次因为需要变更,咱们更改了这个动态变量的值,而后呢我就把这个需要提测了。之后测试反馈给我为什么这边的这个值没有变动啊。
我的天,过后我就是这样,产生了什么状况。而后呢我全量打了个包好了,我过后也就认为只是编译时的一个 bug 而已。而后起初呢,我查了下材料发现这个就是一个 java 编译时的常量优化问题。过了一阵子吧,我面试了下字节跳动,而后我和面试官也聊了下这个话题,而后呢在这个办法签名变更的问题上,过后我略输一筹,哈哈哈哈。接下来咱们就看下一个 demo。
图 1 呢也是 java 代码,图 2 呢则是 aar 中的编译产物。其中咱们能够看到,这个动态常量在编译成产物之后就会被编译成这样。
所以这个就解释了我一开始碰到的这个问题,他就是因为咱们的编译器曾经把 aar 中的这部分动态常量编译成了间接的值,而后呢咱们的源变动之后如果没有从新编译对应的模块,就会导致这个值始终无奈被更新到最新的值。