2. 堆栈文件获取方式:developer options、adb shell命令、bugreport导出
ANR发生后,系统会将主线程的堆栈、CPU使用率、锁竞争等信息写入 /data/anr/traces.txt 或特定包名的trace文件。获取该文件是分析ANR的根本前提。本章介绍三种主流获取方式及其适用场景、操作步骤和常见问题。
课前提示: 所有获取方式均需设备已开启开发者选项和USB调试。部分操作可能需要root或adb shell权限,实际工作中推荐在测试/CI设备上使用adb命令自动化采集。
2.1 开发者选项:即时显示 ANR 堆栈
适用于现场快速查看最近一次ANR堆栈,无需连接电脑。
- 原理: Android 系统在检测到ANR后,会将堆栈信息写入
/data/anr/目录下的文件,并通过开发者选项中的“显示所有ANR”或“显示所有应用程序无响应”开关,在ANR弹窗内直接展示堆栈摘要。 - 操作步骤:
- 进入【设置】→【开发者选项】→ 开启【显示所有ANR】。
- 当ANR发生并被捕获后,系统弹出ANR对话框并显示堆栈入口。
- 点击对话框的“报告”或“查看详情”,可复制部分堆栈;完整堆栈需结合其他方式获得。
- 局限性: 无法获取历史ANR堆栈;弹窗只能展示精简信息;不适用于批量分析。
2.2 adb shell 命令:精准提取 traces.txt
最常用、最可控的方式,适合开发和测试工程师在本地或CI环境中使用。
- 原理: 通过 adb 连接设备,直接读取系统为ANR生成的trace文件。文件路径通常为
/data/anr/traces.txt或按进程编号命名的traces_<PID>.txt。 - 常用命令:
# 查看ANR目录下所有trace文件(需root或系统权限) adb shell ls -l /data/anr/ # 提取完整堆栈并保存到本地 adb shell cat /data/anr/traces.txt > ~/anr_traces/local_traces.txt # 如果权限不足,尝试使用 run-as(仅限debuggable应用) adb shell run-as com.example.myapp cat /data/anr/traces.txt > traces.txt # 或者使用 dumpsys 获取当前ANR信息 adb shell dumpsys dropbox --print data_app_anr | grep -A 200 "Subject: ANR" - 注意事项:
- Android 10及以上版本,普通应用无法直接读取
/data/anr/目录,需使用adb shell su 0 cat或系统应用(如adb shell root权限)。 - 若设备已root,可提前执行
adb root提升权限。
- Android 10及以上版本,普通应用无法直接读取
2.3 bugreport 导出:全量日志 + 堆栈 + 系统信息
适用于复杂ANR问题需要关联系统服务、CPU负载、内存使用等场景。bugreport 是一个压缩包,内含ANR堆栈、logcat、dmesg、内存快照等。
- 生成命令:
# 生成完整bugreport(耗时约1~3分钟) adb bugreport ~/bugreports/ - 堆栈定位: 解压后,在
FS/data/anr/目录下找到traces.txt或分进程trace文件;也可以在dumpstate_board.txt中搜索 “ANR in” 查看汇总。 - 适用场景:
- 系统层级ANR(如InputDispatcher超时)需要结合dmesg分析。
- 多个ANR同时发生时,bugreport能一次性导出所有trace。
- 无法直接连接adb的场景(如用户反馈设备),可让用户通过“设置→开发者选项→错误报告”生成并分享。
2.4 三种方式对比
| 获取方式 | 触发条件 | 文件路径/内容 | 适用场景 | 权限要求 |
|---|---|---|---|---|
| 开发者选项显示ANR | ANR弹窗出现 | 弹窗内摘要 | 现场快速定位 | 无额外权限 |
| adb shell cat traces.txt | 手动执行命令 | /data/anr/traces.txt 全文 |
本地开发、自动化测试 | root或system权限 |
| adb bugreport | 手动执行命令 | 压缩包内 FS/data/anr/ 目录 |
复杂问题、用户反馈、跨系统关联 | 开发者选项开启 |
2.5 获取堆栈流程图
下图展示了ANR发生后,通过三种途径到达 traces.txt 的完整链路:
2.6 常见错误与排查
- 权限错误:
cat: /data/anr/traces.txt: Permission denied。解决方法:使用adb root或以 system 身份执行adb shell "su 0 cat /data/anr/traces.txt"。如果是userdebug/eng镜像,可用adb shell "run-as com.android.shell cat /data/anr/traces.txt"。 - 文件不存在:
/data/anr/traces.txt可能不存在,原因:当前没有发生ANR,或ANR已被系统清理。确保在ANR发生后尽快执行获取命令。可以添加wait循环监控/data/anr/目录变化。 - bugreport 太大: 生成的 zip 可能超过100MB,传输和存储成本高。建议只提取
FS/data/anr/目录,可使用unzip -j bugreport.zip "FS/data/anr/*" -d ~/anr_traces/。 - 开发者选项不显示完整堆栈: 弹窗只显示主线程状态,无法查看其他线程或锁信息。正式分析仍需依赖文件方式。
2.7 性能与稳定性优化建议
- 自动化采集脚本: 在 CI 自动化测试中,建议在测试脚本内集成以下伪代码逻辑:
- 测试启动前,执行
adb shell "echo 1 > /sys/kernel/debug/tracing/tracing_on"(需要内核支持)。 - 测试过程中,每隔30s检查
/data/anr/是否有新文件。 - 若检测到ANR,立即 pull traces.txt 和 logcat,避免被系统自动删除。
- 测试启动前,执行
- 避免频繁 pull 大量数据: 高频率的
cat /data/anr/traces.txt会导致adb传输中断或设备IO压力。推荐在ANR发生后一次性拉取。 - 保持开发者选项开启: 开发机建议常开“显示所有ANR”,方便现场排查;但生产环境用户设备不应开启此选项。