安卓 Android 原生应用 Native 崩溃
捕获流程
- 编译端:编译 C/C++ 代码时,需要将带符号信息的文件保留下来。
- 客户端:捕获到崩溃时候,将收集到尽可能多的有用信息写入日志文件,然后选择合适的时机上传到服务器。
- 服务端:读取客户端上报的日志文件,寻找适合的符号文件,生成可读的 C/C++ 调用栈。
捕获难点
怎样保证在各种极端情况下依然可以生成崩溃日志。
Breakpad 是最成熟方案
- 情况一:文件句柄泄漏,导致创建日志文件失败,怎么办?
- 应对方式:我们需要提前申请文件句柄 fd 预留,防止出现这种情况。
- 情况二:因为栈溢出了,导致日志生成失败,怎么办?
- 应对方式:为了防止栈溢出导致进程没有空间创建调用栈执行处理函数,我们通常会使用常见的 signalstack。在一些特殊情况,我们可能还需要直接替换当前栈, 所以这里也需要在堆中预留部分空间。
- 情况三:整个堆的内存都耗尽了,导致日志生成失败,怎么办?
- 应对方式:这个时候我们无法安全地分配内存,也不敢使用 stl 或者 libc 的函数,因为它们内部实现会分配堆内存。这个时候如果继续分配内存,会导致出现堆破坏或者二次崩溃的情况。Breakpad 做的比较彻底,重新封装了
- 情况四:堆破坏或二次崩溃导致日志生成失败,怎么办?
- 应对方式:Breakpad 会从原进程 fork 出子进程去收集崩溃现场,此外涉及与 Java 相关的,一般也会用子进程去操作。这样即使出现二次崩溃,只是这部分的信息丢失,我们的父进程后面还可以继续获取其他的信息。在一些特殊的情况,我们还可能需要从子进程 fork 出孙进程。
崩溃率计算
UV 崩溃率 = 发生崩溃的 UV / 登录 UV
如何客观地衡量稳定性(ANR)
- 使用 FileObserver 监听
/data/anr/traces.txt
的变化- 海外可以使用 Google Play 服务,而国内微信利用 HardCoder 。HC 框架是一套独立于安卓系统实现的通信框架,它让 App 和厂商 ROM 能够实时“对话”了,目标就是充分调度系统资源来提升 App 的运行速度和画质,切实提高大家的手机使用体验,向厂商获取了更大的权限。
- 监控消息队列的运行时间
- 这个方案无法准确地判断是否真正出现了 ANR 异常,也无法得到完整的 ANR 日志。
- 应用退出的情形
- 主动自杀:Process.killProcess()、exit()
- 崩溃:出现了 Java 或 Native 崩溃。
- 系统重启:系统出现异常、断电、用户主动重启等,我们可以通过比较应用开机运行时间是否比之前记录的值更小。
- 被系统杀死:被 low memory killer 杀掉、从系统的任务管理器中划掉等。
- ANR
- 根据应用的前后台状态,我们可以把异常退出分为前台异常退出和后台异常退出。“被系统杀死”是后台异常退出的主要原因,当然我们会 更关注前台的异常退出的情况 ,这会跟 ANR、OOM 等异常情况有更大的关联。
- 异常率计算:
UV 异常率 = 发生异常退出或崩溃的 UV / 登录 UV
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Android 安卓 移动端网络
下一篇: MyBatis 介绍和使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论