【发布时间】: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 { *; },所有细节都在那里!谢谢!真的很奇怪,仅仅告诉它保持我的模型完好无损是不够的。如果您想将此作为答案发布,我很乐意接受。