- 01.整体介绍概述
- 1.1 项目背景介绍
- 1.2 遇到问题
- 1.3 基础概念介绍
- 1.4 设计目标
- 1.5 产生收益分析
- 02.Native崩溃
- 2.1 Native崩溃有哪些
- 2.2 Native信号机制
- 03.崩溃处理入口
- 04.崩溃监听思路
- 4.1 实现崩溃监听
- 4.2 处理捕获异常
- 4.3 Native捕获难点
- 4.4 崩溃日志收集
- 4.5 捕获指定线程异常
- 4.8 完整的流程
- 05.方案基础设计
- 5.1 整体架构图
- 5.2 UML设计图
- 5.3 关键流程图
- 5.4 接口设计图
- 5.5 模块间依赖关系
- 06.其他设计说明
- 6.1 性能设计
- 6.2 稳定性设计
- 6.3 灰度设计
- 6.4 降级设计
- 6.5 异常设计
- 07.其他说明介绍
- 当native 层发生异常的时候,往往是通过信号的方式发送,给相对应的信号处理器处理
- 发生异常----->发送signal信号----->主进程
- 可以从signal.h看到,大概已经定义的信号有
- signal1,signal2,signal3,signal4,signal5,signal6,……,signal31
- 在java环境中,如果程序出现了不可预期的crash(即没有捕获),就会往上抛出给最终的线程UncaughtExceptionHandler
- native 层的crash大多数是“不可恢复”的,比如某个内存方面的错误,这些往往是不可处理的,需要中断当前进程。
- 最核心的是怎么样保证客户端在各种极端情况下依然可以生成崩溃日志。
- 因为在崩溃时,程序会处于一个不安全的状态,如果处理不当,非常容易发生二次崩溃。那么,生成崩溃日志时会有哪些比较棘手的情况呢?
- 情况一:文件句柄泄漏,导致创建日志文件失败,怎么办?
- 应对方式:我们需要提前申请文件句柄 fd 预留,防止出现这种情况。
- 情况二:因为栈溢出了,导致日志生成失败,怎么办?
- 应对方式:为了防止栈溢出导致进程没有空间创建调用栈执行处理函数,我们通常会使用常见的 signalstack。在一些特殊情况,我们可能还需要直接替换当前栈,所以这里也需要在堆中预留部分空间。
- 情况三:整个堆的内存都耗尽了,导致日志生成失败,怎么办?
- 应对方式:这个时候我们无法安全地分配内存,也不敢使用 stl 或者 libc 的函数,因为它们内部实现会分配堆内存。这个时候如果继续分配内存,会导致出现堆破坏或者二次崩溃的情况。Breakpad 做的比较彻底,重新封装了Linux Syscall Support,来避免直接调用 libc。
- 情况四:堆破坏或二次崩溃导致日志生成失败,怎么办?
- 应对方式:Breakpad 会从原进程 fork 出子进程去收集崩溃现场,此外涉及与 Java 相关的,一般也会用子进程去操作。这样即使出现二次崩溃,只是这部分的信息丢失,我们的父进程后面还可以继续获取其他的信息。在一些特殊的情况,我们还可能需要从子进程 fork 出孙进程。
- 完整的 Native 崩溃从捕获到解析的流程:
- 编译端。编译 C/C++ 代码时,需要将带符号信息的文件保留下来
- 客户端。捕获到崩溃时候,将收集到尽可能多的有用信息写入日志文件,然后选择合适的时机上传到服务器。
- 服务端。读取客户端上报的日志文件,寻找适合的符号文件,生成可读的 C/C++ 调用栈。
- native crash收集流程分析
- https://www.jianshu.com/p/77a53d7b642e
- 鹰眼Android平台崩溃监控实践
- https://mp.weixin.qq.com/s/YSrXx_oTJkp0kRDF6XvzdQ
- Android程序Crash时的异常上报
- https://blog.csdn.net/singwhatiwanna/article/details/17289479
- Java全局异常处理
- https://www.lagou.com/lgeduarticle/107790.html
- 手把手讲解 Android Hook入门Demo
- https://www.jianshu.com/p/74c12164ffca?tdsourcetag=s_pcqq_aiomsg
- 其他一些博客
- https://segmentfault.com/a/1190000020986852?utm_source=sf-related
- https://juejin.cn/post/6854573218171191309
- 爱奇艺
- https://github.com/iqiyi/xCrash
- https://github.com/JZ-Darkal/AndroidHttpCapture