第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 四个 buffergrep -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 -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间接获取
Thread.setDefaultUncaughtExceptionHandler)中直接写本地文件,确保 logcat 丢失时仍有最后防线。
2.5 原因定位:从采集数据到可疑调用链
数据到手后,按照以下顺序快速定位异常线程和调用栈入口:
- 在 logcat 中搜索
signal:找到崩溃信号类型(SIGABRT/SIGSEGV/SIGFPE) - 在 Bugreport 的
traces.txt中查找MediaCodec:找到阻塞或异常线程 - 提取堆栈顶部的
native_方法:如native_dequeueOutputBuffer、native_queueInputBuffer - 对照代码行号:在项目源码中定位对应调用位置
# 快速定位 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 复测:验证采集工具链的可用性
每次修改采集配置或更换测试设备后,必须执行一次“采集演练”:
- 触发一次可控的 MediaCodec 异常(如传入非法分辨率)
- 按 2.2 节流程依次采集 logcat、Bugreport、trace
- 检查三个工具是否都产出了包含
MediaCodec关键字的有效文件 - 验证堆栈顶部方法名是否能对映到代码中
演练通过标准:三次采集均能在 5 分钟内产出可读堆栈,且无关键信息截断。
2.8 预防:建立“三件套”采集基线
将采集流程固化为团队规范,避免临场慌乱:
- 基线一:所有 MediaCodec 相关的 JIRA 或 Bug 单,必须附带 logcat(
-b all)+ Bugreport 两份产物 - 基线二:CI 流水线中增加采集检测步骤,自动检查日志中是否包含
signal或ANR关键字 - 基线三:测试机保持 adb 授权常驻,关闭“USB 选择”弹窗干扰
- 基线四:每周一次采集工具链健康检查,确保 Bugreport 能完整生成
2.9 崩溃日志采集工作流
下图展示了从异常发生到堆栈数据就绪的完整采集链路:
图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 时或手动触发 |