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弹窗内直接展示堆栈摘要。
  • 操作步骤:
    1. 进入【设置】→【开发者选项】→ 开启【显示所有ANR】。
    2. 当ANR发生并被捕获后,系统弹出ANR对话框并显示堆栈入口。
    3. 点击对话框的“报告”或“查看详情”,可复制部分堆栈;完整堆栈需结合其他方式获得。
  • 局限性: 无法获取历史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 提升权限。

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 的完整链路:

ANR 堆栈获取流程 应用发生ANR 开发者选项显示ANR 弹出摘要信息 adb shell cat /data/anr/traces.txt adb bugreport 生成zip包 得到 traces.txt 主线程堆栈 + CPU 状态 工具解析(Python/Chrome trace) 识别锁、IO、CPU瓶颈 说明:adb shell方式最常用,bugreport适合包含系统级信息的全面分析,开发者选项仅作快速预览。

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”,方便现场排查;但生产环境用户设备不应开启此选项。