Proguard 混淆导致 java.lang.IllegalArgumentException:类声明多个名为“a”的 JSON 字段

Posted

技术标签:

【中文标题】Proguard 混淆导致 java.lang.IllegalArgumentException:类声明多个名为“a”的 JSON 字段【英文标题】:Proguard obfuscation results in java.lang.IllegalArgumentException: class declares multiple JSON fields named "a" 【发布时间】:2013-05-13 09:33:07 【问题描述】:

在启动我的应用程序时会记录两个错误,但只是在混淆之后。没有混淆就没有错误。

除非我被误导,否则错误如下:

class 属性声明了多个名为 a 的 JSON 字段

对于类 PropertyDefinition 也是如此。

05/18 03:33:19.465  java.lang.IllegalArgumentException: class PropertyDefinition declares multiple JSON fields named a:  
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:122)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
com.google.gson.Gson.getAdapter(Gson.java:349)
com.google.gson.Gson.toJson(Gson.java:574)
com.google.gson.Gson.toJson(Gson.java:561)
com.google.gson.Gson.toJson(Gson.java:516)
com.google.gson.Gson.toJson(Gson.java:496)
Property.a(SourceFile:210) <see comment in code below noting this code line>
Property.a(SourceFile:68)
bj.a(SourceFile:44)
aA.<init>(SourceFile:339)

05/18 03:33:19.479  java.lang.IllegalArgumentException: class Property declares multiple JSON fields named a:  
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:122)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
com.google.gson.Gson.getAdapter(Gson.java:349)
com.google.gson.Gson.fromJson(Gson.java:790)
com.google.gson.Gson.fromJson(Gson.java:757)
com.google.gson.Gson.fromJson(Gson.java:706)
com.google.gson.Gson.fromJson(Gson.java:678)
Property.a(SourceFile:75) <see comment in code below noting this code line>
bj.a(SourceFile:44)
aA.<init>(SourceFile:339)

这是与几乎相同的错误之一相关的混淆图部分。我在这里和上面没有混淆类名“Property”。我没有看到问题。我没有进一步的混淆经验,所以我不知道要寻找什么。

mypackage.Property:
    mypackage.PropertyDefinition rootElement -> a
    java.util.HashMap indexById -> a
    java.util.HashMap indexByKey -> b
    long nntgID -> a
    43:54:boolean equals(java.lang.Object) -> equals
    60:64:int hashCode() -> hashCode
    68:84:boolean check() -> a
    88:88:java.lang.String getFileName() -> a
    92:92:java.lang.String getDirectory() -> b
    101:102:java.lang.String getVersion() -> c
    107:107:java.util.HashMap getIdIndex() -> a
    112:112:java.util.HashMap getKeyIndex() -> b
    122:122:long getNntgID() -> a
    126:127:void setNntgID(long) -> a
    142:147:void setRootElement(mypackage.PropertyDefinition) -> a
    150:150:mypackage.PropertyDefinition getPropertyDefinitionById(java.lang.String) -> a
    154:154:mypackage.PropertyDefinition getPropertyDefinitionByKey(java.lang.String) -> b
    162:168:java.lang.String toString() -> toString
    210:214:void toFile() -> a

顺便说一句,我的 Proguard 配置中已经有了这个部分:

-keep class com.google.gson**  *; 
-keepclassmembers class com.google.gson** 
   *;

关于从哪里开始故障排除有什么建议吗?

【问题讨论】:

您是否尝试过不混淆(保留)PropertyPropertyDefinition @JoeF 我昨晚最终做到了:-keep public class myPackage.PropertyDefinition *; 和其他几个人。这确实解决了它,但我认为/希望我可以保留类的名称(例如,PropertyDefinition)而不保留所有成员名。到目前为止,我无法让它发挥作用。 【参考方案1】:

您似乎在 proguard-project.txt 中指定了 ProGuard 选项 -overloadaggressively。它将字段名称和方法名称重载为相同的混淆名称,例如'a',只要字段和方法的签名不同。它对类文件有效,但 GSON 显然不喜欢它,所以你应该避免这个选项。

【讨论】:

有趣的是,-overloadaggressively 是各种 Proguard 示例中用于设置 GSON 的推荐选项之一。 如果您还将该选项与 -keep 选项结合使用以保留序列化字段及其原始名称,则该选项是可以的。这也避免了任何名称冲突。【参考方案2】:

只保留类名而不保留成员名不起作用的原因是成员名是导致错误的原因。 Proguard 将多个成员重命名为同名“a”,这在类文件中完全有效。但是,您使用的工具不喜欢有多个同名成员,因此会引发错误。

因此,解决方案是阻止 Proguard 重命名该类的成员。可能还有一个 Proguard 设置来避免重复名称,但我不够熟悉,无法说出它是什么。

【讨论】:

这个答案为我指明了正确的方向。我将-keep class your.package.name.model.** *; 添加为suggested here。

以上是关于Proguard 混淆导致 java.lang.IllegalArgumentException:类声明多个名为“a”的 JSON 字段的主要内容,如果未能解决你的问题,请参考以下文章

Android 库 proguard 包混淆产生 a.a.a.a.a 冲突

ProGuard 导致应用滞后

启用 ProGuard 会导致签名 APK 生成失败?

如何修复因 ProGuard/R8 导致的崩溃?

ProGuard常见问题及解决套路

为啥 proguard 不混淆方法体?