华为应用市场反馈公司的app用户评论里出现了部分Android 9.0手机崩溃的留言,情况紧急,WTF!! Σ(っ °Д °;)っ
image.png单从评论里可以看到部分蛛丝马迹:
- 崩溃出现的时间点比较集中
- 用户是在手机升级到Android 9.0之后,出现的闪退
- 清理数据重启后不再闪退
原因分析:
- 集中出现在那几天,应该就是华为用户升级系统比较密集。
- 升级前app的缓存文件数据,导致了升级后app运行的崩溃。
- 是不是新系统的某种和文件操作相关的特性引起的问题,
还原现场
想要解决这个问题,就需要先还原出现问题的场景。首先需要找公司申请一部华为手机,越新越好,P打头的,o( ̄︶ ̄)o,,,嘿,醒醒!
其次,要想还原场景,就需要把系统从9.0之前升级到9.0,这工程量,想想其实就够了>_<
好吧!还能有什么办法可能模拟类似状况。
铁锅炖自己.png此时,公司大佬的一句话提出一种思路,“可不可以备份9.0之前的数据还原到9.0上”,好吧,试试看。死马当活马医,那就adb backup一下。这个命令在不同手机上支持情况不尽相同,有挺大的几率会失败,厂商也是为了安全,避免数据的泄露。
<application
android:name=".app.XXXApplication"
android:allowBackup="true"
android:icon="@mipmap/launcher"
首先,AndroidManifest.xml中<application节点需要配置allowBackup这个属性,意思为是否允许备份系统和用户数据的属性。
然后进入9.0之前(比如8.0)的系统app,正常操作流程,然后执行adb backup命令,备份数据。
// adb backup [-f ] [-apk|-noapk] [-shared|-noshared] [-all] [-system|nosystem] []
参数:
// -s XXX 连接设备的serial,如果只有一部设备,可以不填,多个必须指定
// -f C://backup/xxx.ab 指定备份文件的目录和文件名,如果不填,就是当前目录的backup.ab
// -apk|-noapk 是否在备份里包含apk或者仅仅只备份应用数据
// -shared|-noshared 是否备份设备共享的SD card内容,默认是-noshare,主要包括内部存储中的音乐、图片和视频,因此为保险起见,建议加上-share
// -all 所有应用,可以指定报名来备份指定应用
// -system|-nosystem 决定-all标签是否包含系统应用,默认的是-system,根据情况可选择是否用-nosystem
adb -s XXX backup -nosystem -noshared -apk xxx.ab com.xxx.xxxxx
最后我们能得到一个backup.ab的文件,接着我们把数据备份的文件还原到9.0系统上,当前系统也应该已经安装有我们的app,并且最好未启动过,或者执行过清理所有数据。还原到命令:
adb restore backup.ab
使用备份/还原出来的数据,我们重新启动Android 9.0上的app,然后果然闪退了,不知道是该高兴呢,还是。。。
image.png原因定位
出现了崩溃,虚拟机会打印出相应的栈信息。
image.png
正式包被混淆了,对应mapping文件,一步一步找到出错的位置。发现这是一段aspectJ注入的代码,用来做事件统计之类的操作,由于使用时对象为空,所以崩溃了( ఠൠఠ )ノ。看到这里,突然觉着有些似曾相识的感觉,上bugly悄悄去,果不其然,之前有过类似的出错,看来是老朋友。
image.png追踪初始化操作,发现并没有什么可能性会导致未被初始化,那就奇了怪了,问题究竟出在哪呢?
image.png测试的包都是加固过的,由于新版本修改过加固工具版本,额~,试试未加固的怎么样?
经过漫长的打包、安装、操作,备份/还原,未加固的包也崩溃了,而且出错信息指向了fastjson解析json的时候,情况看起来有点微妙(微微有点妙)( ̄︶ ̄)↗ ,继续追踪,出问题的地方在刚刚那个问题之前,但是为什么刚刚没有出现这个崩溃?
关键时刻!大佬又出现了,“是不是加固包的crash被吞掉了”。
image.png
查查logcat,发现刚刚的崩溃,果然有这次的log,只不过没有引起系统崩溃,System.err,却没有崩溃,这是什么操作!
image.png image.png然后百度下加固的原理:
Apk加固原理解析
猜测可能的原因是:宿主app在Application的onCreate方法中执行application对象替换操作,将我们的app的application对象替换掉宿主app的application,并执行其onCreate方法,这些替换操作和调用onCreate操作都是在native里执行的,所以java的报错被native以System.err的方式输出了。
image.png然后这个报错导致我们的app执行中断,但是目前还在宿主的Application的onCreate方法中,所以生命周期方法仍然在继续,之后由于终端导致的对象初始化操作未执行,而出现了空指针异常。这个时候的执行已经不在natvie里面了,所以就导致了app的崩溃!!!
解决问题
经过进一步调查,发现这个fastjson的解析异常是由于Android 9.0上加密算法的变化导致的旧数据解析异常了。Android9.0针对加密算法的实现和处理引入了几项变更,好🕳!!
问题原因找到了,场景也复现了,下一步就是解决这个问题了!(/▽\)
这么看来这个问题算是新版本适配的问题了!我们需要针对新的版本出相应的处理,对于解析失败的数据,我们返回空字符来避免错误就好。
Android9加密变更.png
网友评论