前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >kotlin 和 r8 的量子纠缠 | 类加载机制偷鸡

kotlin 和 r8 的量子纠缠 | 类加载机制偷鸡

作者头像
逮虾户
发布2022-10-28 15:59:58
6600
发布2022-10-28 15:59:58
举报
文章被收录于专栏:逮虾户

前言

戏接上文,kotlin升级没想到啊还有一个大坑。我们之前说了我们使用的agp版本是7.0.3,在这个版本的R8竟然会出现kotlin混淆的bug。

断更一个月,不更文的一个原因就是因为最近感觉太菜了,并没有文章素材了。

问题排查

接下来还是一点点进行问题分析,我们先从kotlin元数据开始讲这个问题。

元数据

大家可以参考下官方的这篇文章R8 编译器: 为 Kotlin 库和应用 "瘦身"

kotlin中的一部分类信息都会生成在Metadata注解中,(Metadata就是kotlin元数据)。另外工程内有一部分代码使用了kotlin-reflect的能力,而kotlin-reflect很多能力都是通过读取元数据来完成的。

Kotlin 元数据 是存储在 Java 类文件的注解中的一些额外信息,它由 Kotlin JVM 编译器生成。元数据确定了类文件中的类和方法是由哪些 Kotlin 代码构成的。比如,Kotlin 元数据可以告诉 Kotlin 编译器类文件中的一个方法实际上是 Kotlin 扩展函数。

这个是我通过jadx反编译出来的一个类的信息,我们可以发现很多关键信息都存放在元数据中。其中如果元数据丢失了可能就会影响到的就是一些kotlin和java的互相调用,还有就是一些kotlin-reflect的调用。

但是我们在release混淆包中,这部分kotlin 1.7.10生成出来的元数据竟然被R8代码优化掉了,导致了release包的部分功能异常。

Gradle中的类加载机制

这里要展开这个可能会比较突兀哦,但是其实大家可以继续向下看下去就知道了。

JVM类加载机制、双亲委派和SPI机制

面试中我们经常被问到的一个问题就是类的生命周期,以前的时候我对于这个东西是没有什么概念的,因为毕竟没有什么实际的应用场景,但是这里雀食是有的。

上图就是类的生命周期了,类加载机制有个特性,如果当前的ClassLoader内已经加载过这个类则后续就会使用这个类去完成构造,当然如果不存在则会去挂载jar,然后从jar中去构造出。当然我们一般在写安卓的时候很少会出现加载两个不同版本的jar的情况,但是这个在Gradle编译中是被允许的,所以先后加载jar的顺序就决定了我们会使用哪个版本的jar

我们之前就写过一个很意思的bug,我们在Settings插件内先加载了低版本的AGP,之后我们即时在build.gradle内定义了高版本的AGP,因为类加载机制的原因,也会把AGP锁定在一个低版本上,因为这个jar已经被ClassLoader优先加载了。

单独升级R8

接下来我们就需要偷偷的使用上面的方法,跳过AGP 7.0.3中低版本的R8,直接使用高版本AGP 7.2.1R8就能修复这个异常了。

正常情况下我们都是在build.gradle内的buildscript去定义AGP版本的。这次我们只需要把这个R8的版本放到settings.gralde中就可以解决这个问题了。

代码语言:javascript
复制
buildscript{
  dependencies {
         classpath("com.android.tools:r8:3.2.60")
         classpath('com.google.guava:guava:30.1.1-jre')
  }
}

当然大部分情况下其实我是不建议使用这种黑魔法的,因为经常会出现方法签名等等匹配不上的情况。而R8因为了其中有中间层的特殊性,所以可以比较容易的被替换成另外一个版本。

总结

全TM是坑啊,其实还有好几个问题我都没说。只能说世事无常大肠包小肠。

另外因为我们有一部分方法签名检查的a8就是基于r8开发的,所以后面就可能还有一篇吧。

我打算后续吹嘘下Gradle Enterprise,试用阶段发现真的还是挺好用的。

参考文献

Data class metadata is removed with proguard / R8 for Kotlin 1.6.0

R8 编译器: 为 Kotlin 库和应用 "瘦身"

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 问题排查
    • 元数据
      • Gradle中的类加载机制
        • 单独升级R8
        • 总结
        • 参考文献
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档