1. ANR 定义与现象识别
1.1 现象识别:用户感知与系统反馈
Android ANR (Application Not Responding) 是当应用主线程(UI 线程)被长时间阻塞,无法及时处理用户输入或系统广播时,系统向用户显示的交互阻断对话框。识别 ANR 是问题排查的第一步,核心是区分“用户感知”与“系统日志”两类信号。
用户端典型表现(现象识别清单):
- ANR 对话框: 弹出“应用无响应”窗口,包含“关闭应用”和“等待”两个选项。
- 界面冻结: 点击屏幕、滑动列表无任何视觉反馈,持续 5 秒以上。
- Toast/提示异常: 某些系统版本不弹 ANR 对话框,仅表现为界面卡死后直接闪退。
- 系统级假死: 极少数情况下(system_server ANR),状态栏消失、无法锁屏、按键无反应。
系统日志特征(判断规则): 通过 logcat 可捕获 ANR 事件的关键关键字。以下是与用户感知表现直接对应的日志片段特征:
// 关键日志关键字
// 1. ANR 标题行
"ANR in " + packageName
// 2. 原因摘要
"Reason: " + 原因描述
// 3. CPU 负载报告
"CPU usage from " + 时间戳
// 4. 主线程堆栈
"main" prio=5 tid=1 "状态"
// 5. 等待队列信息
"Waiting in " + 队列类型
现象识别检查表(一线排查规则):
- 用户描述“点不动”、“卡死”、“弹窗说无响应” → 优先怀疑 ANR。
- 检查 logcat 中是否包含 "ANR in" 关键字;无日志但有卡死 → 可能是系统 ANR 或资源耗尽。
- 同一场景下复现率超过 30% → 触发条件明确,进入数据采集阶段。
1.2 ANR 触发条件与系统服务超时阈值
Android 系统为四大组件和输入分发设定了严格的主线程执行时间上限。理解这些阈值是“原因定位”阶段匹配具体代码问题的核心依据。
1.2.1 四大触发路径与超时阈值
| 触发路径 | 系统服务/组件 | 默认超时阈值 | 典型触发场景 |
|---|---|---|---|
| Input Dispatching | WindowManagerService (WMS) | 5 秒 | 点击或触屏事件在 5 秒内未被主线程处理(dispatch 超时) |
| BroadcastReceiver | ActivityManagerService (AMS) | 前台: 10 秒 / 后台: 60 秒 | onReceive() 中执行耗时网络请求或文件读写 |
| Service | ActivityManagerService (AMS) | 20 秒 | onStartCommand() 或 onCreate() 中执行同步阻塞操作 |
| ContentProvider | ActivityManagerService (AMS) | 10 秒 | ContentProvider 的查询/插入操作在主线程中耗时过长 |
阈值差异说明:
- 上述阈值为 Android 10+ 通用默认值。部分厂商(如小米、华为)可能调整后台广播阈值为 120 秒。
- 前台广播 10 秒阈值包含 onReceive() 中启动的 有序广播 链上所有接收器的总耗时。
- Service 的 20 秒阈值不包含 前台服务 通知的启动时间。
1.2.2 触发条件故障树
以下 SVG 展示了 ANR 产生的核心决策逻辑,用于快速定位触发路径。排查时从此树顶层向下匹配。
1.3 排查规则:基于现象快速匹配触发路径
当用户反馈“卡死”行为时,使用以下 判断规则表 从现象反推触发条件。此表用于指导 数据采集 阶段的抽样方向。
| 用户描述 | 常见触发路径 | 优先采集的日志 |
|---|---|---|
| 打开应用就弹出 ANR | Service.onCreate / ContentProvider.onCreate | anr/traces + logcat 启动日志 |
| 点击某个按钮后卡死 | Input Dispatching (5s) | EventLog (am_anr) + 主线程堆栈 |
| 收到推送通知后卡死 | BroadcastReceiver (前台 10s) | 广播 onReceive 日志 + 延迟统计 |
| 后台长时间运行后未响应 | Service (20s) / 后台广播 (60s) | CPU 负载 + 主线程阻塞点 |
| 多任务切换后界面无响应 | Binder 线程池耗尽 / 死锁 | Binder 事务日志 + traces.txt |
1.4 数据采集:从现象到日志的快速抓取
在确认 ANR 现象后,立即执行以下命令组以锁定“罪魁祸首”。这些命令也是后续“原因定位”阶段的主要输入。
# 1. 实时监控 ANR 事件日志(关键字段 am_anr)
adb logcat -b events | grep "am_anr"
# 2. 获取当前 ANR 痕迹文件(Android 10+)
adb shell ls /data/anr/
adb shell cat /data/anr/traces.txt
# 3. 获取系统服务超时统计数据
adb shell dumpsys activity processes
# 4. 查看最近一次 ANR 的完整 logcat(包含 CPU 和堆栈)
adb logcat -d -v threadtime > anr_full.log
数据采集优先级(规则):
- 第一顺位:
/data/anr/traces.txt— 包含所有线程的堆栈快照。 - 第二顺位:Event log 中的
am_anr记录 — 精确到毫秒的时间戳和原因。 - 第三顺位:
dumpsys activity processes— 显示各进程级超时状态。
通过本章内容,排查者应能完成 现象识别 到 数据采集 的衔接。下一阶段(第 2 章)将详细解析 traces.txt 的堆栈解读方法。