前言
最近项目中遇到一个棘手的问题
在打包打开混淆以后 一直报序列化的问题
我是用的Bundle
传输的数据
我开启了序列化混淆 也忽略了实体类 还是报错~~~~
昨天加班到12点多 经过不断的查资料 不断的尝试 最终解决了这个bug 在此记录一下心酸过程...
错误提示及定位
21221-21221/com.app.ldy.mymvvm E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.ldy.mymvvm, PID: 21221
1.//这里加备注 方便看 主要看这里
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.app.ldy.mymvvm.data.bean.Item00)
at android.os.Parcel.writeSerializable(Parcel.java:2116)
at android.os.Parcel.writeValue(Parcel.java:1886)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:978)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1629)
at android.os.Bundle.writeToParcel(Bundle.java:1303)
at android.os.Parcel.writeBundle(Parcel.java:1047)
at android.content.Intent.writeToParcel(Intent.java:10866)
at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:3917)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1731)
at android.app.ContextImpl.startActivity(ContextImpl.java:1033)
at android.app.ContextImpl.startActivity(ContextImpl.java:1004)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:414)
at me.hgj.mvvmhelper.ext.CommExtKt.e(:88)
at com.app.ldy.mymvvm.ui.fragment.PhotoFragment.S(:61)
at com.app.ldy.mymvvm.ui.fragment.PhotoFragment.Q(Unknown Source:0)
at t.c.a(Unknown Source:2)
at com.chad.library.adapter.base.BaseQuickAdapter.U(:596)
at com.chad.library.adapter.base.BaseQuickAdapter$b.onClick(:538)
at android.view.View.performClick(View.java:7704)
at android.view.View.performClickInternal(View.java:7677)
at android.view.View.access$3600(View.java:850)
at android.view.View$PerformClick.run(View.java:29120)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8087)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
2.//这里加备注 方便看 主要看这里
Caused by: java.io.NotSerializableException: com.google.gson.internal.LinkedTreeMap$a
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
错误1
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.app.ldy.mymvvm.data.bean.Item00)
,Parcelable在写入可序列化对象时遇到IOException·
在项目中 这个Item00的子类我也实现了序列化接口了
可以感觉截图看到 我们所有的内部类均实现了
serializable
发现不是这里的错误 继续根据错误提示 排查问题
问题2
Caused by: java.io.NotSerializableException: com.google.gson.internal.LinkedTreeMap
这个错误 根据名称也可以分析是序列化的问题 但是具体是什么错误 不得而知
还得继续查资料
翻阅 stack overflow
我们查到了和这个问题一样的帖子 内心很激动 像是迷路的孩子找到了指明灯
根据问题 找到点赞较高的一个回复
还是混淆规则的问题 有关LinkedTreeMap 写入和读取 没有给予混淆规则说明
导致数据内部 序列化的时候出现错误 非常不好排查
解决方案
以上都是解决问题的出发点和思路
具体解决方法 其实很简单 但是这个原因 还需要自己摸索 通过资料一点点追求原因
我在andrdroid proguard-rules.pro
新增了关于 序列化写入和读取的规则
# Explicitly preserve all serialization members. The Serializable interface # is only a marker interface, so it wouldn't save them.
#显式保留所有序列化成员。可序列化接口
#只是一个标记接口,所以不能保存它们。
关于序列化写入和读取混淆规则如下(解决问题方案 在配置里加入以下规则)
# 显式保留所有序列化成员。可序列化接口只是一个标记接口,因此不会保存它们。
-keep public class * implements java.io.Serializable {*;}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
有关Parcelable
,Serializable
序列化规则 以下是原有的配置
-keepnames class * implements java.io.Serializable
-keepattributes Signature
-keep class **.R$* {*;}
-ignorewarnings
-keepclassmembers class **.R$* {
public static <fields>;
}
总结
遇到一个很难解决的bug 往往需要付出大量的时间
从一些提示或很细小的发现 一步步深入排查
只要有解决bug的决心 结果往往都是好的 问题解决后 心情也是格外的开朗