Android崩溃优化
崩溃优化目标
崩溃优化的核心不是“拦截崩溃”,而是建立稳定性治理闭环:
- 发现:完整采集崩溃现场
- 定位:快速还原调用链和上下文
- 修复:以影响面和复现率排序处理
- 验证:灰度观测 + 回归验证
崩溃类型划分
Java Crash
典型表现:FATAL EXCEPTION,常见来源有NullPointerException、越界、并发状态错误等。
Native Crash
典型表现:signal 11(SIGSEGV)、signal 6(SIGABRT),常见于 JNI/so 层非法访问、释放后访问等。
ANR(补充)
ANR 严格来说不是 crash,但在稳定性治理里应与 crash 一并管理。
补充:ANR 常见可分为四类路径。
- 输入事件超时(Input)
- 广播处理超时(Broadcast)
- 前台/后台服务执行超时(Service)
- 内容提供者调用阻塞(ContentProvider)
OOM 与 LMK 区分(补充)
OOM:进程内申请内存失败,通常以OutOfMemoryError体现。LMK:系统低内存策略直接杀进程,很多场景不会留下完整 Java 崩溃堆栈。
两者都表现为“应用退出”,但治理路径完全不同:
- OOM 重点看内存分配与泄漏
- LMK 重点看进程常驻体积、后台策略与内存水位
采集与现场信息(补充)
稳定性排查最小信息集建议包括:
- 崩溃堆栈(Java/Native)
- 线程快照(主线程 + 关键工作线程)
- 设备与系统信息(机型、系统版本、ABI)
- 应用版本信息(versionCode、渠道、灰度批次)
- 业务上下文(页面、关键参数、最近行为链)
Java 崩溃处理边界
可以通过Thread.setDefaultUncaughtExceptionHandler补充日志与兜底上报,但不要把它当成“防崩溃方案”。
补充:
- Handler 里应避免复杂逻辑,防止二次异常
- 上报后应尽快交还系统默认处理,避免进程进入不一致状态
补充:UncaughtExceptionHandler更适合做“最后一次现场采集”,不适合作为业务恢复机制。
Native 崩溃处理边界
Native 崩溃建议重点做好两件事:
- 采集可符号化的栈信息(含 so 版本与偏移)
- 保留符号文件(
symbols/mapping)用于线上还原
补充:没有符号化信息的 Native 崩溃,修复效率会大幅下降。
补充:若在 signal 回调中做兜底采集,需遵守 async-signal-safe 约束,避免在崩溃现场执行复杂逻辑导致二次崩溃。
符号化链路(补充)
- Java 混淆还原依赖
mapping.txt - Native 符号还原依赖
symbols与 so 构建标识(如 BuildId) - 上报侧需绑定应用版本、abi、构建号,保证离线还原可定位到唯一构建产物
缺少任一环节,都会显著降低问题定位效率。
混合栈排查(补充)
对于 Java -> JNI -> Native 的跨层问题,建议把三段信息串成一条调用链:
- Java 入口调用点
- JNI 桥接方法与参数
- Native 崩溃点与 so 偏移
只看单层栈常常会误判根因。
崩溃治理优先级(补充)
建议按以下维度排序:
- 影响范围(崩溃用户数、崩溃率)
- 触发频率(高频路径优先)
- 业务损失(支付、登录、启动链路优先)
- 修复风险(低风险快修优先)
补充:建议长期跟踪crash-free users与crash-free sessions两类口径,避免只看单一崩溃次数。
常见高价值治理点
- 启动期空指针与初始化时序问题
- 生命周期切换导致的状态失效(Activity/Fragment)
- 并发改写与主子线程竞态
- JNI 参数校验不足与对象生命周期越界
发布与回归(补充)
- 重要修复建议灰度放量,观察崩溃率趋势
- 保证每次发布都可追溯对应
mapping和symbols - 对高发问题建立回归用例,避免同类问题反复出现
补充:可增加 Crash Loop 防护策略。
- 在本地记录连续崩溃次数与时间窗口
- 超过阈值进入安全模式(关闭高风险开关/插件)
- 保障用户至少可进入应用核心页面
小结
崩溃优化本质是工程体系建设:
“采集完整 -> 定位高效 -> 修复可控 -> 验证闭环”,持续降低稳定性风险。
Android崩溃优化
https://leo-wxy.github.io/2019/07/20/Android-崩溃优化/