1. 课程导入

Android 系统的稳定性问题,最终几乎都会落到内核与底层运行时上。应用层 ANR、Native Crash、系统重启、黑屏、死机、频繁掉帧,表面看是 App 或 Framework 的问题,但真正难以定位、影响面最大的,往往是内核崩溃、内存越界、驱动异常、锁竞争、Watchdog 超时、低内存回收失败等底层故障。本课程的目标,是建立一套从“现象”到“根因”的系统化诊断能力,而不是停留在抓一份 log 或 tombstone 就结束。

本课程围绕三条主线展开:稳定性机制(内核如何保证系统不崩)、故障信号(崩溃时系统留下哪些证据)、诊断方法(如何从证据反推根因并验证修复)。

一、学习目标:从“会看日志”到“能定位根因”

很多工程师第一次接触 Crash 诊断时,习惯直接搜索关键字,例如 “kernel panic”“Fatal signal”“watchdog”。这种方式能快速找到异常点,但无法回答三个关键问题:故障发生在哪个子系统?触发条件是什么?修复后如何验证不再复现?本课程希望达成的学习目标如下:

  • 理解 Android 稳定性分层模型:应用层、Framework 层、Native 层、内核层、硬件层各自的责任边界与故障表现。
  • 掌握常见崩溃类型:Kernel Panic、Oops、Watchdog、Native Crash、ANR、LMK 杀进程、重启、死机。
  • 能读懂关键日志与现场:dmesg、last_kmsg、pstore/ramoops、tombstone、ANR trace、bugreport、ftrace、perfetto。
  • 能使用调试工具链:adb、logcat、gdb/lldb、addr2line、objdump、crash、drgn、perf、ftrace、KASAN、KMEMLEAK。
  • 能建立诊断闭环:复现、采集、分析、定位、修复、回归验证、监控预防。

二、核心概念:稳定性诊断的五个关键词

在进入具体章节之前,需要先统一几个核心概念,否则后续分析容易混淆。

概念含义典型信号
Crash进程或内核异常终止,无法继续执行SIGSEGV、SIGABRT、Kernel Panic
ANR应用主线程长时间无响应ANR trace、Input dispatching timed out
Watchdog系统关键服务或内核线程超时未喂狗Watchdog bite、system_server 重启
LMK低内存杀手回收进程以维持系统可用lowmemorykiller、kill 日志
Pstore/Ramoops重启后保留上一次内核崩溃现场console-ramoops、dmesg-ramoops

其中,Crash 是结果,不是原因。诊断的核心不是“谁崩了”,而是“为什么会在此时此地崩”。例如同样是 SIGSEGV,可能是空指针、野指针、栈溢出、内存踩踏,也可能是驱动 DMA 越界导致用户态地址被破坏。只有把信号、现场、调用栈、内存状态、时间线结合起来,才能接近根因。

三、整体知识框架:从应用到内核的稳定性地图

下图给出本课程的整体知识框架。它把 Android 稳定性问题按层级展开,并标出每层最值得关注的故障类型、证据来源与诊断工具。学习时可以先建立这张地图,再逐章深入。

Android 稳定性与 Crash 诊断知识框架 分层定位 · 证据链采集 · 根因反推 · 修复验证 应用层 / Java 层 Java Crash · ANR · 主线程阻塞 · Binder 超时 · 内存泄漏 logcat / ANR trace Framework / System Server Watchdog · system_server 重启 · Service 超时 · 死锁 · 广播风暴 bugreport / dumpsys Native / HAL / 驱动接口 SIGSEGV · SIGABRT · tombstone · JNI 越界 · HAL 崩溃 · 内存踩踏 tombstone / addr2line Linux Kernel Kernel Panic · Oops · 空指针 · 锁竞争 · OOM · LMK · 文件系统异常 dmesg / pstore / crash 硬件 / SoC / 电源 DDR 异常 · 温度保护 · 电压不稳 · 看门狗复位 · 存储坏块 串口日志 / 硬件寄存器 诊断闭环 复现 → 采集 → 分析 → 定位 → 修复 → 回归验证 → 监控预防 工具:adb · ftrace · perfetto · KASAN · gdb

这张框架图有两个使用要点。第一,自下而上定位:如果内核已经 panic,优先看 pstore/ramoops 和串口日志,而不是只翻 logcat。第二,自上而下验证:如果应用频繁崩溃,也要确认是否由底层内存不足、驱动异常或系统服务重启引起。很多“应用问题”最终根因在内核。

四、实战路线图:七步诊断法

为了让学习过程可操作,本课程把诊断流程归纳为七步。后续章节会围绕这七步逐步展开。

  1. 现象分类:区分重启、死机、黑屏、ANR、Native Crash、Java Crash,确定影响范围与复现概率。
  2. 现场保护:第一时间保留 bugreport、dmesg、pstore、tombstone、ANR trace,避免重启后证据丢失。
  3. 时间线对齐:把 logcat、kernel log、system log、ftrace 按时间戳对齐,找到第一个异常点。
  4. 调用栈解析:对 Native Crash 使用 addr2line、objdump、gdb 还原符号与代码行。
  5. 根因假设:根据内存、锁、驱动、电源、调度等方向提出可验证假设。
  6. 实验验证:通过复现脚本、压力测试、KASAN、ftrace、perf 验证假设。
  7. 修复与回归:提交补丁,补充监控,执行稳定性压测与回归验证。
建议在真实项目中建立“稳定性证据包”规范:一次故障至少包含 bugreport、dmesg、pstore、tombstone、ANR trace、复现步骤、版本信息、硬件信息。证据越完整,定位越快。

五、典型场景与常见误区

举一个常见场景:设备在待机时偶发重启。初级分析可能只看到 “Watchdog bite”,于是认为是 system_server 卡死。但进一步查看 pstore 会发现内核在更早时间出现 Oops,导致关键线程无法调度,Watchdog 只是“最后倒下的人”。如果只修 Watchdog 超时时间,问题会继续复现。正确做法是沿着 Oops 的调用栈追到具体驱动或内存越界点。

常见误区包括:

  • 只看 logcat,不看 kernel log 与 pstore,导致根因被掩盖。
  • 把 Watchdog 当作根因,而不是当作系统失稳的结果。
  • 忽略时间线,把多个独立故障混在一起分析。
  • 没有符号表就分析 Native 栈,得到错误函数名。
  • 修复后不做压力回归,导致问题在特定场景再次出现。
稳定性诊断最忌讳“猜一个原因就改”。每一个结论都应有日志、栈、寄存器、内存状态或实验数据支撑。没有证据链的修复,只是碰运气。

六、本课程的学习方法

建议按“概念—机制—工具—案例—复盘”的节奏学习。每章先理解机制,再动手采集与分析真实日志;遇到案例时,先自己判断根因,再看解析。课程中的命令、日志片段和参数都可以在模拟器或开发板上复现。最终目标不是记住某个崩溃的答案,而是掌握一套可迁移的诊断方法:无论面对 Kernel Panic、Native Crash 还是 ANR,都能快速建立证据链,找到根因,并验证修复。

# 常用现场采集命令示例
adb bugreport bugreport.zip
adb shell dmesg > dmesg.txt
adb shell cat /sys/fs/pstore/console-ramoops > ramoops.txt
adb shell ls /data/tombstones/
adb shell cat /data/anr/traces.txt > anr_traces.txt
adb shell dumpsys activity processes > processes.txt

当你能够把一次崩溃从“现象”还原为“时间线 + 调用栈 + 内存状态 + 触发条件”,并且能用实验证明修复有效,就已经具备 Android 内核稳定性诊断的核心能力。接下来各章将围绕这张知识地图逐层展开。