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 产生的核心决策逻辑,用于快速定位触发路径。排查时从此树顶层向下匹配。

ANR 触发条件故障树 ANR 触发(主线程阻塞>阈值) 输入事件阻塞 广播超时 Service/Provider超时 UI线程死锁 异步回调未释放 View绘制超时 Binder调用阻塞 onReceive()耗时操作 Handler.postDelayed() 有序广播链过长 goAsync()未调用 同步网络请求 数据库I/O阻塞 ContentProvider查询慢 Binder线程池耗尽 排查规则:从具体场景节点向上匹配触发路径,对应超时阈值 各分支对应超时阈值 输入事件超时:5 秒(前台窗口不可交互) 前台广播超时:10 秒(onReceive 必须在 10 秒内返回) 后台广播超时:60 秒(不推荐使用广播做长耗时操作) Service 超时:20 秒(建议使用 IntentService 或 WorkManager) ContentProvider 超时:10 秒(URI 查询必须在主线程 10 秒内完成)

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
数据采集优先级(规则):
  1. 第一顺位:/data/anr/traces.txt — 包含所有线程的堆栈快照。
  2. 第二顺位:Event log 中的 am_anr 记录 — 精确到毫秒的时间戳和原因。
  3. 第三顺位:dumpsys activity processes — 显示各进程级超时状态。

通过本章内容,排查者应能完成 现象识别 到 数据采集 的衔接。下一阶段(第 2 章)将详细解析 traces.txt 的堆栈解读方法。