Proguard 使用 kotlin-reflect 为所有 INSTANCE 字段生成注释

Proguard generating notes for all INSTANCE fields with kotlin-reflect

我已将 kotlin-reflect 库添加到我的 Android 项目中,现在 Proguard 生成了数百行注释,列出了所有具有名为 [=11] 的字段的 classes =],这当然包括每一个 Kotlin object.

这里只是 Proguard 输出的一小部分:

Note: kotlin.reflect.jvm.internal.KClassImpl$Data$objectInstance accesses a declared field 'INSTANCE' dynamically
      Maybe this is program field 'co.zsmb.example.proguardkttest.MySingleton { co.zsmb.example.proguardkttest.MySingleton INSTANCE; }'
      Maybe this is program field 'kotlin.UNINITIALIZED_VALUE { kotlin.UNINITIALIZED_VALUE INSTANCE; }'
      Maybe this is program field 'kotlin.Unit { kotlin.Unit INSTANCE; }'
      Maybe this is program field 'kotlin._Assertions { kotlin._Assertions INSTANCE; }'
      Maybe this is program field 'kotlin.collections.EmptyIterator { kotlin.collections.EmptyIterator INSTANCE; }'
      Maybe this is program field 'kotlin.collections.EmptyList { kotlin.collections.EmptyList INSTANCE; }'
      Maybe this is program field 'kotlin.collections.EmptyMap { kotlin.collections.EmptyMap INSTANCE; }'
      Maybe this is program field 'kotlin.collections.EmptySet { kotlin.collections.EmptySet INSTANCE; }'
      Maybe this is program field 'kotlin.comparisons.NaturalOrderComparator { kotlin.comparisons.NaturalOrderComparator INSTANCE; }'

如你所见,它既包括我自己的 MySingleton class,也包括许多来自 Kotlin 标准库的 class图书馆也一样,如果它们存在的话。

错误的第一行告诉我们这里出了什么问题,它发现无论kotlin.reflect.jvm.internal.KClassImpl$Data$objectInstance是什么,它都在通过反射访问一个名为INSTANCE的字段。 Proguard 无法判断此代码​​访问了哪个 class 的 INSTANCE 字段,因此它会警告我们每个具有此字段的 class 以防万一。

如果我们在某些情况下查看source of KClassImpl, we'll find the culprit quickly: it contains a property called objectInstance, which calls the Class#getDeclaredField方法,传入一个值为"INSTANCE"的常量作为参数。这就是 Proguard 正在检测的内容。

所以,除非你有一个单例 class,并且你通过它的 KClass 访问它的实例,就像这样:

val instance = MySingleton::class.objectInstance

您可以在 proguard-rules.pro 文件中添加以下规则来忽略 Proguard 注释:

-dontnote kotlin.reflect.jvm.internal.KClassImpl$Data$objectInstance**

您也可以精确地以 objectInstance 结尾,但库中的实现更改可能会在将来更改该位置编号。这样,您将忽略所有关于 objectInstance 属性 及其实现的注释。