在Android平台,native crash一直是crash里的大头。native crash具有上下文不全、出错信息模糊、难以捕捉等特点,比java crash更难修复。
一、为什么会产生Native Crash?
常见导致Native Crash的原因有以下几种:
1. jni内部数组越界、缓冲区溢出、空指针、野指针等;
2. jni中多线程出现竞争,比如一个线程调用jni接口释放了内部一个指针,另一个线程调用另外一个jni接口还在使用这个指针;
3. Android ART发现或出现异常;
4. 其他framework、Kernel或硬件bug;
二、现有的方案
| 方案 |
优点 |
缺点 |
|---|---|---|
| Google Breakpad | 权威,跨平台 | 代码体量大 |
| 利用Logcat日志 | 利用Android系统实现 | 需要在crash时启动新进程过滤logcat日志,不可靠 |
| coffeecatch | 实现简介,改动容易 | 存在兼容性问题 |
Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合,具有权威、跨平台等优点,其实现原理如下图所示。

Breakpad由三个主要组件:
- client:以library的形式内置在你的应用中,当崩溃发生时写 minidump文件
- symbol dumper:读取由编译器生成的调试信息(debugging information),并生成 symbol file
- processor:读取 minidump文件 和 symbol file ,生成可读的c/c++ Stack trace.
由于google-breakpad是夸平台开源工具,体量较大,在其基础上生成的通用so和dmp日志也都较大,对于sdk大小有严格要求的APP,可能不是很方便。Logcat日志虽然是利用Android系统实现,但是需要在crash时启动新进程过滤logcat日志,而且不可靠。因此,下面介绍一种体量较小的基于c/c++异常信号处理的NativeCrash日志收集方法,其实现原理如下图所示。

三、信号机制
1、用户态和内核态
介绍信号机制之前,我们先来了解两个概念,即用户态和内核态。
用户态(User Mode):运行用户程序。
内核态(Kernel Mode):运行操作系统程序。
用户态和内核态是操作系统的两种CPU状态。
CPU状态之间的转换如下图所示。

2、信号机制
信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号。应用程序运行在用户态,当遇到系统调用、中断或异常的情况时,程序会进入内核态。信号涉及到了这两种状态之间的转换,其转换过程如下图所示。

(1) 信号的接收
接收信号的任务是由内核代理的,当内核接收到信号后,会将其放到对应进程的信号队列中,同时向进程发送一个中断,使其陷入内核态。注意,此时信号还只是在队列中,对进程来说暂时是不知道有信号到来的。
(2) 信号的检测
进程陷入内核态后,有两种场景会对信号进行检测:

最低0.47元/天 解锁文章





