1、崩溃分类
Android崩溃分为两类,分别是Java崩溃和Native崩溃。Java崩溃就是产生在Java代码中的异常,未捕获而导致程序退出。而Native崩溃一般都是因为在Native代码中访问非法地址、地址对齐出现问题或者程序主动abort,这些都会产生相应的signal信号,导致程序异常退出。
2、Native崩溃捕获流程
- 编译端。编译C/C++代码时,需要将带符号信息的文件保留下来。
- 客户端。捕获到崩溃时,将收集到尽可能多的有用信息写入到日志文件,然后选择合适的时机上传到服务器。
-
服务端。读取客户端上报的日志文件,寻找合适的符号文件,生成可读的C/C++调用栈。
Native崩溃捕获
3、Native崩溃捕获难点
Chromium的Breakpad是目前Native崩溃捕获中最成熟的方案,Native崩溃捕获会遇到很多难点:
- 文件句柄泄漏,导致创建日志文件失败
应对:提前申请文件句柄fd预留,防止出现这种情况。 - 栈溢出了,导致日志生成失败
应对:通常使用常见的signalstack,在一些特殊情况,可能还需要直接替换当前栈,所以需要在堆中预留部分空间。 - 整个堆内存耗尽了,导致日志生成失败
应对:Breakpad做的比较彻底,重新封装了Linux S也是callSupport,来避免直接调用libc。 - 堆破坏或二次崩溃导致日志生成失败
应对:Breakpad会从原进程fork出子进程去手机崩溃现场,此外涉及与Java相关的,一般也会用子进程去操作。
4、崩溃现场
崩溃现场保留着很多有价值的线索,是我们解决问题的重要信息,丰富和准确的崩溃现场能够帮助我们快速解决问题,接下来主要看看崩溃现场通常需要采集哪些信息。
1)崩溃信息
- 进程名、线程名
- 崩溃堆栈和类型。崩溃是属于Java崩溃、Native崩溃,还是ANR,对于不同的类型我们的关注点不同
2)系统信息 - Logcat。这里包含应用、系统的运行日志
- 机型、系统、厂商、CPU、ABI、Linux版本等
- 设备状态,是否Root,是否为模拟器等
3)内存信息 - 系统剩余内存
- 应用使用内存, 包括Java内存、RSS(Resident Set Size)、PSS(Proportional Set Size)
- 虚拟内存
4)资源信息 - 文件句柄fd
- 线程数
- JNI
5)应用信息 - 崩溃场景,发生在哪个Activity或Fragment,发生在哪个业务中
- 关键操作路径,通过打点,记录用户的关键操作路径
-其他自定义信息
5、崩溃分析
第一步:确定重点
a、确认严重程度
b、崩溃基本信息
- Java崩溃,常见NullPointerException空指针,OutOfMemoryError资源不足
- Native崩溃,需要观察signal、code、fault addr等内容,以及崩溃时的Java的堆栈。
- ANR,检查主线程是否有耗时操作,是否因为锁等地导致,再观察iowait、CPU、GC、system sever等信息。进一步确认是io问题,或者是CPU竞争,还是大量GC导致的
c、Locat,日志包含了大量有用的信息,可以尝试分析,不放过任何问题
d、各个资源情况,综合所有信息,分析原因
第二步:查找共性
比如机型、系统、厂商、CPUD等是否有相同点
第三步:尝试复现
能够复现的崩溃,就可以获得更多的现场信息,也会更加容易发现问题
6、疑难问题
- 查找可能的原因
- 尝试规避
- Hook解决
网友评论