使用Proguard/R8混淆Kotlin 1.6.0中的数据类元数据被移除。

5

我有一个包含一些数据类的包,并且我正在尝试使用Kotlin反射在运行时访问构造函数clazz.primaryConstructor。一切都按预期工作,但是当我启用R8时,数据类元数据被删除,因此例如当我检查KClass isData是否为假时,它会返回false,并且主构造函数也为空,这仅在启用R8时发生。

我尝试了所有方法,包括给所有数据类添加@keep注释,以及添加保留models包中所有内容的规则,我还添加了以下规则:

-keep class kotlin.reflect.**

-keep class kotlin.Metadata { *; }

但仍然没有运气,有任何想法是哪里出错了或如何修复此问题?

示例存储库

提前致谢。

1个回答

18
问题的原因是,与Android Studio - Arctic Fox捆绑在一起的AGP 7.0中包含的R8不能正确处理Kotlin 1.6.0的元数据。
如果在AGP 7.0中使用Kotlin 1.6.0 (classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.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正在忽略规则,因为只有在启用R8时clazz.primaryConstructor为空,而clazz.isData为false。 - Ahmad Mahmoud Saleh
感谢您抽出时间创建示例。 我无法运行它,因此我创建了一个示例Android应用程序并复制了您的代码,但我仍然面临相同的问题。 https://github.com/ahmadmssm/DataClassR8 - Ahmad Mahmoud Saleh
1
感谢提供示例。我发现问题与Kotlin 1.6.0有关,并更新了上面的答案,希望这能解决您的问题。另外一条评论:在您的示例中,您使用了kotlin-reflect 1.5.31,您应该将其与您的Kotlin版本保持一致。 - sgjesse
1
感谢您报告回来。我已在答案中添加了一条注释,以将kotlin-reflect的版本与Kotlin编译器的版本对齐。 - sgjesse
1
我也遇到了同样的问题,但是我使用的是AGP 7.2.2。我升级到了AGP 7.4.2(gradle 7.5),并且我也成功解决了这个问题。谢谢!我使用了与原帖相同的proguard规则。 - Stefan Indaco
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接