第1章:Crash治理概述
什么是Crash?
咱们做 Android 的,没人没遇到过 Crash。说白了,就是你的 App 在执行一段代码时,遇到了它无法处理的情况,然后直接“罢工”了。更技术一点的说法:Crash 是程序运行时产生了未捕获的异常,或者收到了操作系统发出的致命信号,导致进程被强制终止。
我记得刚入行时,有个同事的 App 总在某个页面闪退,查了好久才发现是空指针。那种挫败感,相信大家都懂。
Crash 主要分两类:
- Java Crash:由 Java 或 Kotlin 代码抛出的未捕获异常引发,比如
NullPointerException、IndexOutOfBoundsException。最常见,也好定位。 - Native Crash:发生在 C/C++ 层面,由
signal触发,比如SIGSEGV(段错误)、SIGABRT(中断)。多跟 JNI、So 库相关,排查起来比较头疼。
看看这个分类表,能帮你快速判断问题类型:
| Crash 类型 | 触发机制 | 典型错误 | 排查难度 |
|---|---|---|---|
| Java Crash | 未捕获异常 (Throwable) |
NullPointerException |
★☆☆ |
| Native Crash | 系统信号 (signal) |
Segmentation fault |
★★★ |
我个人的小习惯:接到 Crash 反馈,先看日志里有没有 Exception 字眼。如果有,基本是 Java 层问题;如果只有一堆内存地址和寄存器信息,那八成是 Native 挂了。
Crash 的影响
一个 Crash 看似是代码层面的小故障,但它带来的连锁反应,往往超出预期。我见过一个很典型的案例:某个版本因为一个空指针导致启动页频繁闪退,用户反馈差评率一度飙到 30%,直接影响了当月的新增用户量。
具体来说,Crash 的影响体现在以下几个方面:
- 用户体验断崖式下跌——用户正刷着视频,突然 App 闪退。一次两次还能忍,频繁出现,用户大概率会卸载。
- 业务数据直接受损——关键页面(比如支付、下单)发生 Crash,意味着转化率下降,真金白银的流失。你想想看,一个支付流程在最后一步崩溃,用户会怎么想?
- 开发效率被拖垮——线上 Crash 频发,团队不得不花大量时间排查、打补丁、发紧急修复版本。我曾在项目中连续两周都在修线上问题,新功能根本推不动。
- 品牌口碑受损——App Store 或应用市场的差评,哪怕只有几十条,也足以劝退潜在用户。很多用户并不会给你第二次机会。
核心观点:Crash 治理不是「锦上添花」,而是「雪中送炭」。一个稳定的 App,才是用户体验和商业转化的基础。
治理目标与原则
搞清楚了 Crash 是什么,以及它有多痛,我们再来聊聊怎么治。我个人习惯把 Crash 治理分成三个层次:
- 零闪退——听起来很理想化,但应该是我们追求的最终目标。尤其是核心路径(启动、登录、支付),要做到极致稳定。
- 快速发现——Crash 不能被用户先发现。通过监控系统,在用户反馈前就收到告警。我曾经因为晚发现了一个线上 Crash,导致用户投诉累积了整整一个周末,真的很被动。
- 根源治理——不要只打补丁,要从代码层面、流程层面解决问题。比如空指针,可以用 Kotlin 的 null safety 特性,或者团队定个规范:所有可能的 null 值都必须显式处理。
- 自动恢复——对于非致命异常,可以考虑通过
UncaughtExceptionHandler做一些兜底处理,比如重启 App 或者引导用户反馈。但这招要慎用,不能掩盖真正的 bug。
治理原则,我提炼了四个字:「防、快、准、改」。
- 防:代码审查、静态检测、单元测试,把问题扼杀在开发阶段。
- 快:建立实时监控和告警体系,Crash 发生后 5 分钟内通知到人。
- 准:精确归因,能定位到具体行号、堆栈、设备、系统版本。
- 改:不仅修复 Crash,还要改进开发流程,避免同类问题再次发生。
避坑指南:我曾经接手过一个项目,线上 Crash 率很高,但团队只盯着监控数字看,从不回头复盘。结果就是每个版本都在修旧 bug,新 bug 又不断出现。后来我们强制要求:每个 Crash 修复后,必须写一份根因分析文档,并在团队内分享。效果立竿见影。
这其实就是 Crash 治理的完整闭环。从预防到发现,再到修复和复盘,缺一不可。下面这张图可以帮你快速理解这个体系: