java命令一闪而过_Java

目前 mPaaS Android 是使用的是 Crash SDK 对闪退进行的处理,Crash SDK 是 Android 平台上一款功能强大的崩溃日志收集 SDK,有着极高的崩溃收集率和完整、全面的崩溃日志信息,生成的日志内容非常利于问题的跟进和解决。

在我们的日常运维中,经常遇到一些闪退,无法直接从闪退堆栈看到原因,尤其是一些非 Java 的 Native 的闪退,这里分享下在 mPaaS 框架下怎么使用 Crash SDK 对闪退进行分析。

闪退报文分析工具介绍

对于 mPaaS 的用户,从 MAS 上闪退分析平台导出的一般是原始的闪退信息,闪退信息比较多,如果直接阅读会比较困难,使用者可以通过下载 Chrome 的插件LogAnalyzer。

LogAnalyzer 会将 Crash SDK 生成的日志文本内容转化成可视效果较强的 HTML 页面展现,功能还是很强大的,主要包含:

高亮显示日志中重点信息,并使用不同颜色区分;

支持日志内容整体结构预览,快速定位重点内容;

常见崩溃原因提醒;

安装好 Chrome 插件后,还需要做以下配置

1. 修改闪退文件后缀为 .txt

由于 MAS 上默认下载的文件后缀是.dat,需要改为.txt,否则 LogAnalyzer 会不识别。

2. 修改插件配置

由于 Chrome 默认权限限制,任何 Chrome 插件默认都不能访问文件网址,需要在 Chrome 插件中进行如下操作。

1.打开 Chrome 插件管理页面 chrome://extensions/

2.找到 LogAnalyzer 插件,点击 “详细信息" 进入设置:

java命令一闪而过_java接入阿里云日志闪退_02

3.找到允许访问文件网址选项,并勾选;

4.打开或者刷新日志页面,LogAnalyzer 就生效了。

3. 生效效果

把日志文件直接拖到 Chrome 后,可以看到右边插件生效后,可以通过不同颜色显示闪退信息的各个字段。

首次打开后的使用说明如下:

java命令一闪而过_java命令一闪而过_03

正常查看闪退截图如下:

java命令一闪而过_java命令一闪而过_04

闪退分析举例

我们经常在日常运维中遇到一些非 Java 的 Native 模块闪退,比如 UC。这种时候很多时候只能去联系 UC 团队进行支撑,其实很多场景下,闪退的根因并不是 UC,只是最后的闪退点在 UC。

以最近日常运维中比较常遇到的 UC 内核的闪退为例,对一些案例的处理分享如下。

1. Java 空指针导致 UC 闪退

我们在闪退点上可以看到以下闪退(已经隐藏客户 apk 相关信息),如果只是从这看我们暂时没有任何线索,我们继续往下看日志:

java命令一闪而过_Chrome_05

当看到 logcat 节点信息的时候,我们发现了线索,首先我们看到关键字:begin to generate native report,表示当前是闪退日志上报的日志,我们再往前看,logcat 节点里打印了异常堆栈信息。

从堆栈信息可以看到,是由于 precreate 操作触发了底层的空指针,从而导致初始化异常,最后触发了闪退。解决方案就是临时关闭预创建,从而规避了闪退。

java命令一闪而过_闪退_06

从上面的案例我们可以看出:

Native 的闪退不一定是 Native 模块的原因导致的,有可能是由于 Java 导致的异常,从而导致 Native 闪退;

begin to generate native report 附近可以看闪退相关的 logcat 信息,协助定位闪退的一些上下文日志。

2. 上层 OOM 导致 UC 闪退

首先我们看上报的闪退点的日志如下图所示,闪退在了 RenderThread 里,也是毫无头绪。

java命令一闪而过_闪退_07

我们继续硬着头皮往下看,在 logcat 节点里查找 begin to generate native report 上报节点,我们看到了大量的底层 OOM 的异常日志,基本大概率确定是 OOM 的原因了。

剩下的就是查找 OOM 是哪里触发的。

java命令一闪而过_java接入阿里云日志闪退_08

点击闪退里的内存节点,基本原因就比较清晰了,当前手机的 Vmsize 基本已经到最大了,我们知道对于 32 位的进程,APP 可使用的 VmSize 最大为 3GB,不过当运行在 64 位 CPU 上时,VmSize 最大可超过 3GB,接近 4GB。

但是由于内核需要占据一部分,以及不同的 ROM 版本的差别,我们发现有以下规律:Android 8.1.0 及之后的系统,大部分 native oom crash 发生时 VmSize 分布在 3.5 - 3.9 G 的位置,相对较为集中。所以下面的案例的解决思路就变成了怎么解决 OOM 了。

java命令一闪而过_闪退_09

3. FD 误关导致 UC 闪退

上报的日志如下图所示,我们大概只能看出 SIGILL 有可能是主动崩溃,崩溃 ILL_ILLOPC 表示非法操作。

java命令一闪而过_java命令一闪而过_10

然后我们继续看 logcat 节点的 begin to generate native report, 基本确认原因是因为 UC 使用的 FD 对象被其他程序关闭。

java命令一闪而过_java接入阿里云日志闪退_11

随后 UC 提供了带 FDscan 的工具包,通过我们复现后发现,是由于 UC 调用 shouldIntercept 回调的输入流对象被其他模块 close 掉了,导致 UC 使用的时候发现 FD 对象已经被关闭,从而做了崩溃处理。最后的处理方案就变成了用户解决其他模块的误关 FD 的问题。

java命令一闪而过_闪退_12

总结

综合以上的 Case 分析,在遇到 Native 模块闪退的时候,一般如果从直接的闪退堆栈看不出原因的时候,不要心急,可以搜索 begin to generate native report 找到崩溃上下文,多看看 logcat 闪退上下文的日志,会有一些收获,同时对于 oom 类型的问题,可以结合当前内存统计来看。