1. 减少启动崩溃率 可以使用 安全模式
2. 异常退出的情形
- 自动自杀
- 崩溃出现 Java或者Native崩溃
- 系统重启
- 被系统杀死,被 low memory killere 杀掉,从系统的管理器中划掉
ANR
3. Native异常捕获
breakpad 谷歌开源 地址breakpad
4.崩溃信息的采集
- 崩溃信息
- 进程名、线程名。崩溃的进程是前台进程还是后台进程,崩溃是不是发生在ui线程
- 崩溃堆栈和类型。崩溃是属于 Java 崩溃、Native 崩溃还是ANR
- 系统信息
- Logcat 这里包括应用、系统的运行日志。由于系统权限问题,获取到的 Logcat可能只包含与当前App相关的,系统的event logcat会记录App运行的一些基本情况,记录在文件/syatem/etc/event-log-tags中,命令行1.adb shell 2. cat/system/etc/event-log-tags adb命令参考
- 机型、系统、厂商、CPU
- 设备状态 :是否root 、是否模拟器
- 内存信息
OOM、ANR、虚拟内存耗尽等,很多崩溃都和内存有直接关系
- 系统剩余内存,关于内存状态,可以直接读取文件 /proc/meminfo,当系统内存很低,系统会进行大量GC,系统频繁的自杀拉起非常容易出现问题
- 应用使用内存。包括Java内存、RSS(Resident Set Size) 、PSS(Proportional Set Size),我们可以得出应用本身内存的占用大小和分布。PSS和RSS通过/proc/self/smap
- 虚拟内存,虚拟内存可以通过 /proc/self/status 得到,通过/proc/self/maps 文件可以得到具体的分布情况
- 资源信息
有的时候我们会发现应用堆内存和设备内存都非常充足,还是会出现内存分配失败的情况,这跟资源泄漏可能有比较大的关系。
- 文件句柄 fd。文件句柄的限制可以通过 /proc/self/limits获得,一般单个进程允许打开的最大文件句柄个数为1024,但是如果文件句柄超过800个就比较微信,需要将所有的fd以及对应的文件名输出到日志中,进一步排查是否出现了有文件或者线程的泄露
- 线程数。当前线程数大小可以通过上面的status文件得到,过多线程会对虚拟内存和文件句柄带来压力,如果线程数超过400就比较危险了
- JNI.通过DumpReferenceTables 统计 JNI 的引用表,进一步分析是否出现了 JNI 泄漏等问题。
- 应用信息,自己开发的业务模块中记录一些关键操作路径,崩溃场景等
崩溃分析(三部曲)
第一步:确定重点
1. 确认严重程度
2. 崩溃基本信息
- java崩溃,通过android studio 查看崩溃类型,
- Native崩溃,需要观察signal、code、fault addr等内容,以及崩溃时Java的堆栈,关于signal含义的介绍可以查看崩溃信号介绍 比较常见的是SIGSEGV和SIGABRT,前者一般是由于空指针、非法指针造成,后者主要因为ANR和调用abort()退出所导致
- ANR
- Logcat
- 各个资源情况,比如系统内存不足,虚拟内存不足等 或者文件句柄fd泄露
第二步:查找共性
比如是不是因为安装了Xposed或者是不是只有某款机型上有问题等等
第三步 尝试复现
疑难问题:系统崩溃
1. 查找可能原因
2. 尝试规避,是不是使用了不恰当的API,是否可以更换其他的实现方式规避
3. Hook 这里分为Java Hook和 Native Hook ,是不是因为系统版本问题,导致处理不同