第2章:崩溃日志采集工具与方法

本章聚焦数据采集阶段,讲解如何通过 logcat、Bugreport 和 trace 文件高效捕获 MediaCodec 崩溃现场的堆栈数据。正确的采集姿势能直接决定定位效率——采集不全或错误,后续分析就是空中楼阁。

2.1 现象识别:哪些场景必须采集堆栈

不是所有 MediaCodec 异常都需要完整堆栈采集。只有满足以下任一特征时,才启动本章的工具链:

现象特征 典型表现 采集优先级
进程闪退(crash) 应用突然消失,桌面恢复 最高,必须采集
ANR 无响应 界面卡死超过 5s 高,建议采集
编解码无声画面 无崩溃但输出异常 按需采集
内存剧增后重启 OOM 后被系统 kill 高,必须采集
判断规则:只要出现 signal 6 (SIGABRT)、signal 11 (SIGSEGV) 或 input: channel '...' ~ Consumer closed 这类日志关键字,立即启动采集流程,不要等待复现。

2.2 数据采集:三大工具的定位与配合

本章核心工具只有三个:logcat(实时流水)、Bugreport(系统快照)、trace 文件(线程堆栈)。它们各自解决不同维度的信息缺口。

2.2.1 logcat:第一现场的“黑匣子”

logcat 是 Android 最直接的日志管道。MediaCodec 异常通常会输出包含 MediaCodec、ACodec、OMX、NuPlayer 等标签的错误信息。

采集命令:

# 实时捕获 MediaCodec 相关日志,写入文件
adb logcat -v threadtime -b all | grep -E "MediaCodec|ACodec|OMX|NuPlayer|signal|CRASH" > codec_crash_$(date +%Y%m%d_%H%M%S).log

关键参数说明:

  • -v threadtime:显示线程 ID 和时间戳,堆栈分析必备
  • -b all:同时捕获 main、system、events、crash 四个 buffer
  • grep -E:过滤出 MediaCodec 相关行,减少噪声
避坑:不要只抓 -b main!MediaCodec 底层 OMX 错误经常只出现在 -b system 或 -b crash 中,漏 buffer 等于漏证据。

2.2.2 Bugreport:系统级的“全景快照”

Bugreport 是一个包含 CPU 负载、内存状态、进程列表、内核日志、ANR trace 等 30+ 份诊断报告的 ZIP 包。当发生 ANR 或系统级 MediaCodec 崩溃时,它是还原现场最完整的依据。

采集命令:

# 生成完整 bugreport(耗时约30s)
adb bugreport ./bugreport_mediaCodec_$(date +%Y%m%d_%H%M%S).zip

Bugreport 内与 MediaCodec 相关的关键文件:

文件/路径 查找重点
bugreport-<device>-<datetime>.txt 搜索 MediaCodec、OMX、Codec2、NuPlayer
dumpstate_board.txt 硬件编解码器状态、DSP 固件版本
anr/traces.txt ANR 时所有线程的堆栈,重点找 MediaCodec.native_dequeueOutputBuffer
events.log am_anr、am_crash、service_crash 事件

2.2.3 trace 文件:线程级堆栈的“冰冻切片”

当 logcat 显示 threadid=<tid>: stuck on 'MediaCodec' 或 ANR 时,系统会自动生成 /data/anr/traces.txt。也可以手动触发采集:

# 手动触发所有进程 trace(需 root 或 eng 版本)
adb shell kill -3 <PID>

# 或者直接拉取 ANR trace
adb pull /data/anr/traces.txt ./traces_$(date +%Y%m%d_%H%M%S).txt

trace 文件中的 MediaCodec 典型堆栈片段:

----- pid 12345 at 2025-04-07 10:15:30 -----
Cmd line: com.example.player

"CodecLoop" prio=5 tid=13 Blocked
  at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
  at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3458)
  - waiting to lock <0x0a1b2c3d> (a android.media.MediaCodec)
  at com.example.player.MediaCodecHelper.processOutput(MediaCodecHelper.java:89)

2.3 采集时序:什么时候用什么工具

核心原则:先 logcat 保底,再 Bugreport 补全,最后 trace 定线程。三个工具不是“三选一”,而是“三连拍”。
场景 首选工具 辅助工具 采集窗口
进程闪退 logcat -b crash Bugreport(事后) 崩溃后 30s 内
ANR Bugreport trace 文件、logcat -b events ANR 发生后立即
编解码无声/花屏 logcat -b all Bugreport(按需) 问题持续期间
OOM 被 kill logcat -b events Bugreport + trace kill 后 1min 内

2.4 采集故障树:常见失败原因与补救

采集过程本身也可能失败。以下故障树列出 80% 的采集异常场景:

  • logcat 无输出 → 检查 USB 授权、adb 版本;换 adb logcat -c 清空 buffer 后再试
  • Bugreport 生成失败 → 磁盘空间不足(需 >500MB);adb shell dumpsys 先验证系统状态
  • trace 文件为空 → 进程已死;改用 adb shell cat /proc/<PID>/stack 获取最后堆栈
  • 权限不足 → 非 root 设备无法 pull /data/anr/traces.txt;使用 adb bugreport 间接获取
备用方案:当 adb 离线时,可以在 App 内集成日志采集模块,在崩溃回调(Thread.setDefaultUncaughtExceptionHandler)中直接写本地文件,确保 logcat 丢失时仍有最后防线。

2.5 原因定位:从采集数据到可疑调用链

数据到手后,按照以下顺序快速定位异常线程和调用栈入口:

  1. 在 logcat 中搜索 signal:找到崩溃信号类型(SIGABRT/SIGSEGV/SIGFPE)
  2. 在 Bugreport 的 traces.txt 中查找 MediaCodec:找到阻塞或异常线程
  3. 提取堆栈顶部的 native_ 方法:如 native_dequeueOutputBuffer、native_queueInputBuffer
  4. 对照代码行号:在项目源码中定位对应调用位置
# 快速定位 MediaCodec 堆栈的 grep 组合
grep -n -B5 -A20 "MediaCodec" traces.txt | grep -E "native_|at com\."

2.6 修复动作:基于采集缺失的补救措施

如果发现采集数据不完整,需要立即执行修复动作,而不是盲目重复测试:

数据缺失类型 修复动作 命令行/操作
logcat 缺失 system buffer 重新采集,加 -b system adb logcat -b system -v threadtime | grep MediaCodec
Bugreport 无 traces.txt 手动触发 trace 后重新生成 adb shell kill -3 <PID> 再拉取
trace 文件无时间戳 添加 -v threadtime 重新抓 logcat 见 2.2.1 命令
所有工具均无输出 启用 App 内本地日志,复现后直接读取文件 实现 UncaughtExceptionHandler + 文件写入

2.7 复测:验证采集工具链的可用性

每次修改采集配置或更换测试设备后,必须执行一次“采集演练”:

  1. 触发一次可控的 MediaCodec 异常(如传入非法分辨率)
  2. 按 2.2 节流程依次采集 logcat、Bugreport、trace
  3. 检查三个工具是否都产出了包含 MediaCodec 关键字的有效文件
  4. 验证堆栈顶部方法名是否能对映到代码中

演练通过标准:三次采集均能在 5 分钟内产出可读堆栈,且无关键信息截断。

2.8 预防:建立“三件套”采集基线

将采集流程固化为团队规范,避免临场慌乱:

  • 基线一:所有 MediaCodec 相关的 JIRA 或 Bug 单,必须附带 logcat(-b all)+ Bugreport 两份产物
  • 基线二:CI 流水线中增加采集检测步骤,自动检查日志中是否包含 signal 或 ANR 关键字
  • 基线三:测试机保持 adb 授权常驻,关闭“USB 选择”弹窗干扰
  • 基线四:每周一次采集工具链健康检查,确保 Bugreport 能完整生成

2.9 崩溃日志采集工作流

下图展示了从异常发生到堆栈数据就绪的完整采集链路:

崩溃日志采集工作流 MediaCodec 崩溃日志采集工作流 ① App崩溃/ANR ② 选择采集方法 ③ logcat 实时捕获 -b all + grep 过滤 ④ Bugreport 系统快照 30+ 诊断报告打包 ⑤ trace 线程堆栈 /data/anr/traces.txt ⑥ 三路堆栈数据聚合 ⑦ 异常堆栈解析与定位 关键判断规则 闪退 → 优先查 logcat -b crash 中的 signal 号 | ANR → 优先解压 Bugreport 中的 traces.txt | 无响应 → 优先看 native_ 方法栈顶

图2-1 崩溃日志采集工作流:三个工具各自捕获不同维度的现场数据,最终汇聚到堆栈解析环节。

2.10 本章要点速查

工具 核心命令/操作 主要用途 采集时机
logcat adb logcat -b all -v threadtime 实时日志,信号与异常消息 崩溃/ANR 发生时立即
Bugreport adb bugreport ./bugreport.zip 系统全景快照 + ANR trace ANR 后或定期采集
trace 文件 adb shell kill -3 <PID> 线程堆栈快照 ANR 时或手动触发
一句话记忆:闪退找 signal 看 logcat,ANR 解 bugreport 读 traces.txt,无响应抓 native_ 方法栈顶——三件套齐了再动手修复,不要凭感觉猜。