带有 Proguard 的 Kotlin 反射失败

Posted

技术标签:

【中文标题】带有 Proguard 的 Kotlin 反射失败【英文标题】:Kotlin Reflection with Proguard fails 【发布时间】:2019-06-24 21:40:17 【问题描述】:

假设我有这门课

data class Person(val name: String?)

当我 proguard 并运行应用程序时,我收到以下异常

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: No accessors or field is found for property val com.whatever.packagee.Person.name: kotlin.String?

我还发现这个问题是从这个reflection 代码库引发的。任何帮助将不胜感激

【问题讨论】:

请说明您在代码中究竟是如何使用反射的。 我实际上是在使用 Moshi 序列化 JSON。 用@Keep注解类,防止被proguard修改。 @RobCo 我已经在 proguard 规则中添加了它。 -keep, -keepclassmembers 用于带有通配符的整个包。 也许见github.com/square/moshi/issues/315 【参考方案1】:

请确保不要使用太宽泛的 -keep 选项,这会妨碍 ProGuard 正确优化和缩小代码。

保留您希望序列化的类的字段很重要。根据您看到的异常,我希望类似于下面的 -keep 选项可以解决问题;

-keep class com.whatever.packagee.Person 
    <fields>;

您可以通过 ProGuard Playground 试验这些 -keep 选项,这对于查看哪些代码部分受您的 -keep 规则影响非常有用。通过这种方式,您可以检查是否处理了所有序列化案例。我为这种特殊情况创建了一个 Playground:Playground link

【讨论】:

【参考方案2】:

这为我解决了这个问题。

在proguard规则中添加以下内容

-保持类 kotlin.reflect.jvm.internal.**

-keep class kotlin.Metadata *;

【讨论】:

以上是关于带有 Proguard 的 Kotlin 反射失败的主要内容,如果未能解决你的问题,请参考以下文章

kotlin android proguard错误

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

Proguard 和 Kotlin 的“找不到引用的类”

启用 Proguard 时未找到 kotlin.Any

R8 去除反射所需的 Kotlin 伴生对象

Kotlin 反映 proguard SmallSortedMap