序列化/反序列化和Proguard

10

我使用的一款应用程序中,当我尝试更新我的APK时,我的一个序列化类出现了问题。

实际上,这与先前版本apk中保存的对象和新版本apk有关的问题有关。

在最新的APK(在Android Market上生产)中,我忘记为可序列化的类(以及它们的静态final long serialVersionUID成员)配置我的proguard.cfg...

因此,当我尝试在新的APK中重新加载先前存储的可序列化类时,在StackTrace DDMS中会出现InvalidClassException问题:

04-24 18:17:40.120: W/System.err(1204): java.io.InvalidClassException: cu; Incompatible class (SUID): cu: static final long serialVersionUID =6593847879518920343L; but expected cu: static final long serialVersionUID =0L;
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.verifyAndInit(ObjectInputStream.java:2380)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1662)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:683)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1803)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:787)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2003)
04-24 18:17:40.125: W/System.err(1204):     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1960)

我知道这是与可序列化对象及其serialVersionUID有关的混淆问题...

在这里阅读了 Proguard 和 Serialized Java Objects 之后,清楚地暴露了我的问题,但我仍然无法解决它...

在我的下一个 APK 中,我已经在我的 proguard.cfg 中添加了这个:

-keepnames class * implements java.io.Serializable

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient ;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
为了避免未来更新中的问题,我真的需要找回这些旧对象...
我尝试使用6593847879518920343L或0L更改serialVersionUID,但没有成功...
有什么建议吗?
非常感谢您的答复!
1个回答

5
您可以尝试以下方法:
  1. 计算混淆后的可序列化类的serialVersionUID,并将其添加到当前源代码中。
  2. 混淆新代码,保留serialVersionUID,但同时确保可序列化类被映射到早期混淆的名称(使用选项-applymapping)。

9
如何计算混淆后可序列化类的 serialVersionUID? - peceps
2
这个答案缺少如何实现解决方案的示例代码。 - McFarlane
1
@peceps 你可以通过编写一个自定义的ObjectInputStream,在反序列化期间打印出这些值来计算已序列化类的serialVersionUIDs。例如,参见this answer - V.S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接