获取 ANR 日志:抓证据的三种武器

遇到 ANR,第一反应是什么?

我个人的习惯是,先别急着看代码。先找证据。

你想想看,现场都还没保护起来,你拿什么去分析? ANR 定位这件事,说白了就是侦探破案。你得先有案发现场的记录,才能去推理凶手是谁。

所以这一章,咱们就聊聊获取 ANR 日志的三种主要方法。 trace 文件、 logcat、 bugreport。每种方法都有各自的脾气和适用场景,用对了能省一半时间。

ANR 日志获取策略 ANR 发生 /data/anr/traces.txt logcat 命令行 bugreport 报告 核心线程堆栈快照 适用于:所有 ANR 场景 保存现场、排查死锁 实时日志流 适用于:开发测试阶段 快速定位、复现问题 系统级全量诊断包 适用于:深度、复杂场景 结合 trace/CPU/内存分析 核心思路 轻量取证 → trace文件(最快获取现场) 线索梳理 → logcat(追踪过程) 全景分析 → bugreport(完整复盘)

一、trace 文件:ANR 现场的第一手笔录

只要系统检测到 ANR,就会自动把当时所有线程的堆栈信息 dump 到 /data/anr/traces.txt 文件里。

它记录了「那一刻」你的 App 到底在执行什么代码。哪个方法卡住了主线程,一目了然。

⚠️ 重要提示: Android O(8.0)之后,每个 App 的 trace 文件会分开存放,文件名格式通常是 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/activityActivityManager 状态,能看到 ANR 的进程是谁以及具体原因
⚠️ 使用限制:
bugreport 有个明显的缺点:文件太大。尤其在线上或测试机内存不足时,生成过程可能因为系统资源紧张而失败。我建议在以下场景再用它:
- 问题已经被稳定复现,需要做深度根因分析。
- 排查涉及 Binder 死锁、跨进程超时、系统服务卡顿等复杂问题。

三种方法怎么选?一张表说清楚

获取方法 信息宽度 获取速度 适用场景
trace 文件 ★★☆☆☆ ★★★★★ 快速取证,主线程堆栈分析
logcat ★★★☆☆ ★★★★☆ 开发测试阶段,实时定位
bugreport ★★★★★ ★★☆☆☆ 深度复盘,复杂场景根因分析

你想想看,这三种方法其实是递进关系。早期排查先用 trace 文件秒定现场;觉得不对劲再用 logcat 找前因后果;问题比较隐蔽就上 bugreport 做全面分析。

我在工作中通常把它们组合起来用:

  1. 遇事不决,先拉 trace。
  2. 配合 logcat 看过程,确认是不是系统侧的问题。
  3. 如果往深了走,果断生成 bugreport。

嗯,拿到这些日志之后,下一步才是真正的分析环节。但今天我先把工具和获取方法讲清楚,工具顺手了,分析才能事半功倍。