获取 ANR 日志:抓证据的三种武器
遇到 ANR,第一反应是什么?
我个人的习惯是,先别急着看代码。先找证据。
你想想看,现场都还没保护起来,你拿什么去分析? ANR 定位这件事,说白了就是侦探破案。你得先有案发现场的记录,才能去推理凶手是谁。
所以这一章,咱们就聊聊获取 ANR 日志的三种主要方法。 trace 文件、 logcat、 bugreport。每种方法都有各自的脾气和适用场景,用对了能省一半时间。
一、trace 文件:ANR 现场的第一手笔录
只要系统检测到 ANR,就会自动把当时所有线程的堆栈信息 dump 到 /data/anr/traces.txt 文件里。
它记录了「那一刻」你的 App 到底在执行什么代码。哪个方法卡住了主线程,一目了然。
traces_你的包名.txt。怎么拿?
方法其实不复杂。我给个最稳的流程:
// 1. 确认文件存在
adb shell ls -l /data/anr/traces*
// 2. 拉取到本地(需要 root 权限,大部分场景下 adb shell 无法直接读取)
adb shell "cat /data/anr/traces.txt" > traces_local.txt
// 3. 如果遇到权限不足,先执行
adb root
adb remount
// 4. 再次尝试拉取
adb pull /data/anr/traces.txt ./
我曾经遇到过一个坑:在某个定制 ROM 的设备上,trace 文件被写到了 /data/anr/traces/traces_包名.txt 这个更深层的目录里。结果找了半小时没找到。后来发现是厂商改规则了。
获取 trace 文件的时间窗口很关键。ANR 发生后,系统可能会在下一个 ANR 发生时覆盖旧文件。我个人建议,一旦发现 ANR,第一时间执行
adb shell cat 命令,别等到去泡茶。二、logcat:追踪 ANR 前因后果的日志流
trace 文件只能告诉你「在哪里发生了死锁或卡顿」,而 logcat 能告诉你「在这之前发生了什么」。
举个例子,ANR 之前有没有大量 IO 操作?有没有低内存的 alert?有没有其他进程抢占资源?这些信息都在 logcat 里。
过滤技巧
我常用的过滤命令:
// 只看 ANR 相关日志
adb logcat -b main -b system -b crash *:I | grep -i "anr"
// 查看 CPU 使用率变化的日志
adb logcat -b events | grep "anr"
// 带上时间戳,持续输出到文件
adb logcat -v time -b all > anr_logcat.txt
有个细节要注意:logcat 的 buffer 是有限的。如果 ANR 发生时间较早,logcat 里的日志可能已经被冲掉了。所以我建议,在测试阶段就把日志实时导出到 PC 端,不要等出了问题再打开 logcat。
✅ 开发调试阶段:你正在操作,ANR 复现了,立刻看 logcat。
✅ 需要定位「谁发送了耗时广播」或「内部服务是否响应超时」。
三、bugreport:全景式的案发现场还原
如果说 trace 是照片,logcat 是视频片段,那 bugreport 就是一部纪录片。
bugreport 把系统几乎所有的状态都打包了:
- 所有线程的堆栈(相当于把多个 trace 文件合起来)
- 当前的 CPU 使用率和各核运行频率
- 内存状态、Binder 调用栈
- 进程列表以及每个进程的优先级
- 网络、传感器、功耗等辅助信息
生成方法
// 直接生成完整的 bugreport(耗时约 15-30 秒)
adb bugreport
// 生成后会得到一个 zip 文件,解压后有 dumpsys、dumpstate、logcat 等子文件
生成后,我会重点关注以下几个文件:
| 文件 / 目录 | 关键内容 |
|---|---|
| FS/data/anr/ | 包含当时的 trace 文件,可直接查看 |
| dumpstate_log.txt | 系统诊断日志,包含 ANR 触发的大致时间点 |
| events.log | 事件日志,可以看到 ANR 前后的系统事件链路 |
| dumpsys/activity | ActivityManager 状态,能看到 ANR 的进程是谁以及具体原因 |
bugreport 有个明显的缺点:文件太大。尤其在线上或测试机内存不足时,生成过程可能因为系统资源紧张而失败。我建议在以下场景再用它:
- 问题已经被稳定复现,需要做深度根因分析。
- 排查涉及 Binder 死锁、跨进程超时、系统服务卡顿等复杂问题。
三种方法怎么选?一张表说清楚
| 获取方法 | 信息宽度 | 获取速度 | 适用场景 |
|---|---|---|---|
| trace 文件 | ★★☆☆☆ | ★★★★★ | 快速取证,主线程堆栈分析 |
| logcat | ★★★☆☆ | ★★★★☆ | 开发测试阶段,实时定位 |
| bugreport | ★★★★★ | ★★☆☆☆ | 深度复盘,复杂场景根因分析 |
你想想看,这三种方法其实是递进关系。早期排查先用 trace 文件秒定现场;觉得不对劲再用 logcat 找前因后果;问题比较隐蔽就上 bugreport 做全面分析。
我在工作中通常把它们组合起来用:
- 遇事不决,先拉 trace。
- 配合 logcat 看过程,确认是不是系统侧的问题。
- 如果往深了走,果断生成 bugreport。
嗯,拿到这些日志之后,下一步才是真正的分析环节。但今天我先把工具和获取方法讲清楚,工具顺手了,分析才能事半功倍。