【问题标题】:Kotlin: ProGuard erases properties attributesKotlin:ProGuard 擦除属性属性
【发布时间】:2017-04-22 23:15:15
【问题描述】:

TL;DR:启用 proguard 后,使用反射时,我的属性看起来是私有的、不可为空且没有注释,尽管 proguard 配置应该保留所有这些属性。

我有一些简单的 data classes 具有公共属性,可用作我的 Android 应用程序中的数据模型。稍后,在对所述类进行通用 [反] 序列化时,我会像这样过滤属性列表:

val properties = instance::class.memberProperties
        .filter { it.visibility == KVisibility.PUBLIC } // && some other conditions, unrelated here
        .filterIsInstance<KMutableProperty<*>>()

它在我的调试版本上正常工作(我的意思是它选择了我想要的属性)。但是,在进行 release 构建时,proguard 处于活动状态,结果为空。为了检查原因,我记录了一个类属性的所有相关信息——结果它们的visibility 字段读取为PRIVATE(所有其他属性与调试版本相同)。

我已经在 proguard 配置中有一行来保留所有模型:

-keepclassmembers class * extends com.models.package.name.BaseModel { *; }

我之前试过这个,结果一样:

-keep class com.models.package.name.** { *; }

proguard 为什么/如何影响属性可见性?我应该以某种方式修改配置吗?还是我在这里错过了其他东西?


更新:似乎可见性不是唯一的。 prop.returnType.isMarkedNullable 也不起作用,它为声明为 null 的属性返回 false。并且注释似乎也丢失了,即使我要求 proguard 保留它们。有没有办法解决这个问题?这几乎让我两周的工作毫无用处......

【问题讨论】:

  • 丢失的信息存储在@KotlinMetadata 注释中。您需要确保您的 ProGuard 配置不会删除这些注释。
  • @yole 我的 proguard 配置中有:-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod。所以根本不应该删除任何注释。对于我的模型类的-keep 命令,它们根本不应该被剥离,不是吗?也许您知道任何 proguard 技巧可以做到这一点?
  • 我个人对proguard没有太多经验。您可以在 proguard 之后对 .class 文件使用 javap 以确保注释存在。
  • 实际上,您提出了正确的建议!我必须将 proguard 告诉-keep class kotlin.Metadata { *; },所有细节都在那里!谢谢!真的很奇怪,仅仅告诉它保持我的模型完好无损是不够的。如果您想将此作为答案发布,我很乐意接受。

标签: android proguard kotlin


【解决方案1】:

感谢@yole 在问题 cmets 中的建议,我已经能够完成这项工作。即使我的类被配置为由 ProGuard 保存,它也会从它们中剥离 kotlin.Metadata 注释。这些注释是 Kotlin 存储我缺少的所有属性的地方。解决方案是防止ProGuard删除它们,添加到配置中:

-keep class kotlin.Metadata { *; }

(附带说明:奇怪的是它没有包含在默认配置中,至少如果您使用的是kotlin.reflect.full 包。或者至少应该在文档中的某处清楚地提及它......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-13
    • 2016-12-13
    • 2011-01-29
    • 2018-07-11
    • 1970-01-01
    • 2022-01-17
    • 2012-07-19
    • 1970-01-01
    相关资源
    最近更新 更多