如果你有其它想法,欢迎和我交流
前几天在开发中遇到一个比较少见的 crash,记录一下,截图如下:
log1
log2
分析过程
观察 log1 没办法直接定位到问题,尝试搜索关键信息 android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v4.app.FragmentManagerState
https://blog.csdn.net/hecate1994/article/details/100126101
从搜索结果看类似问题发生的场景是在页面状态保存恢复时,也就是 onSaveInstanceState() 、onRestoreInstanceState(),因为类加载器 ClassLoader 不对,导致序列化反序列化出错,但是日志中没看到上面两个方法,也没有其他有用信息
查看 Activity 源码,发现 dump() 调用时机是在运行 adb shell dumpsys activity <activity_component_name>,感觉不像 crash 发生的场景
观察 log2,发现该页面并没有用到崩溃信息里的 ViewPager,这就很奇怪了
继续搜索关键信息 android.os.BadParcelableException: ClassNotFoundException when unmarshalling
https://issuetracker.google.com/issues/36955416#c1
结合前面的分析,确实在 log2 中看到了状态保存恢复时用到的方法 onRestoreInstanceState()
log2 异常页面里没有用到错误信息里出现的 ViewPager,有没有可能 log2 指向的异常页面应该是 log1 的页面
可以看到两个崩溃时间前后相差 60 秒,而且 log1 中的异常页面,有用到 ViewPager+Fragment 多 tab 切换,而且也是 log2 中页面的入口
大胆的推测,可能原因是 log1 页面触发了状态保存恢复,由于某些原因恢复状态时 ClassLoader 不对,进而反序列化出错导致该 crash
解决办法
1、try catch 出错方法 onRestoreInstanceState()
2、在 onRestoreInstanceState() 中设置 savedInstanceState.setClassLoader(getClass().getClassLoader()),这个有待验证
遗留问题
为什么 log2 的异常页面和堆栈信息对不上
简单重现
使用错误的 ClassLoader 反序列化对象,可以重现 android.os.BadParcelableException: ClassNotFoundException when unmarshalling
这里正确的是应该使用 Person.class.getClassLoader(),间接印证了上面的猜想