使用 proguard / R8 删除数据类元数据

Posted

技术标签:

【中文标题】使用 proguard / R8 删除数据类元数据【英文标题】:Data class metadata is removed with proguard / R8 for Kotlin 1.6.0 【发布时间】:2022-01-15 18:41:31 【问题描述】:

我有一个包含一些数据类的包,我试图在运行时使用 Kotlin 反射 clazz.primaryConstructor 访问构造函数, 一切都按预期工作,但是当我启用 R8 时,数据类元数据被删除,例如,当我检查 KClass isData 是否返回 false 并且主构造函数也是 null 时,这仅在启用 R8 时发生。 我尝试了所有方法,包括向所有数据类添加 @keep 注释并添加规则以将所有内容保留在模型包中,我还添加了这些规则

-keep class kotlin.reflect.**

-keep class kotlin.Metadata  *; 

但仍然没有运气,知道出了什么问题或如何解决这个问题吗?

Sample Repo

提前致谢。

【问题讨论】:

【参考方案1】:

问题是与 AGP 7.0 捆绑在一起的 R8(与 android Studio - 北极狐一起发布)无法正确处理 Kotlin 1.6.0 的 Kotlin 元数据。

如果将 Kotlin 1.6.0 (classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0") 与 AGP 7.0 一起使用,则需要 R8 版本 3.0.77 来压缩 Kotlin 库和使用 kotlin-reflect。更新到 AGP 7.0.4 是不够的,因为该版本与 R8 3.0.76 捆绑在一起。

要使用 R8 3.0.77,请将以下内容添加到您的 settings.gradlesettings.gradle.kts

pluginManagement 
    buildscript 
        repositories 
            mavenCentral()
            maven 
                url = uri("https://storage.googleapis.com/r8-releases/raw")
            
        

        dependencies 
            classpath("com.android.tools:r8:3.0.77")
            classpath('com.google.guava:guava:30.1.1-jre')
        
    

AGP 7.0 的另一个选择是使用 Kotlin 1.5.31。

还可以考虑将您的 kotlin-reflect 版本与 Kotlin 编译器的版本保持一致。

【讨论】:

感谢您回答@sgjesse,但我仍然面临同样的问题,感觉就像R8 忽略了规则,因为clazz.primaryConstructor 仅在启用R8 时为空,clazz.isData 也是错误的。 您使用的是哪个版本的 Android Studio / Android Gradle 插件?您是否将默认 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') 用于标准规则?我用androidx.annoation.Keep 注释的data 类创建了一个小示例项目,它与kotlin-reflect 一起工作(测试isDataprimaryConstructor)。示例项目是github.com/sgjesse/KotlinDataClasses。我提到的其他保留规则不是必需的,因为它们由 kotlin-reflect 提供。 感谢您抽出宝贵时间创建示例。我无法运行它,所以我创建了一个示例 Android 应用程序并复制了您的代码,但我仍然面临同样的问题。 github.com/ahmadmssm/DataClassR8 感谢您提供样品。我发现这个问题与 Kotlin 1.6.0 有关,并更新了上面的答案,希望能为您解决问题。另一条评论:在您使用 kotlin-reflect 1.5.31 的示例中,您可能也应该将其与您的 Kotlin 版本保持一致。 感谢您的反馈。我添加了一条评论,将 kotlin-reflect 的版本与 Kotlin 编译器的版本对齐到答案中。

以上是关于使用 proguard / R8 删除数据类元数据的主要内容,如果未能解决你的问题,请参考以下文章

无法从 R8 配置中删除“-ignorewarnings”(Android Proguard 问题)

在 Android 中使用 R8 和 Proguard 时如何保护数据模型类免受逆向工程的影响?

Android/java:从 ProGuard 到 R8 的过渡/迁移?

同时使用 ProGuard 和 R8

Proguard和R8有啥区别?

如何修复因 ProGuard/R8 导致的崩溃?