遇到Android设备突然卡死、应用闪退或者系统自动重启时,很多开发者会陷入"盲人摸象"的困境。我处理过最棘手的一个案例是某款智能手表在连续使用3小时后必然重启,但常规日志里没有任何异常记录。这种偶发性问题往往需要建立系统性的排查思维。
Android系统的稳定性问题就像一座冰山,我们看到的崩溃现象可能只是水面上的10%,而真正的根源深藏在水下。完整的排查路径应该包含四个层级:
每个层级都有对应的"破案工具":
当看到"Application Not Responding"弹窗时,新手常犯的错误是直接看/data/anr/traces.txt。其实更高效的做法是:
bash复制adb shell cat /data/anr/anr_* | grep -A 30 "Binder starvation"
这个命令能快速定位到关键阻塞点。我最近分析的一个电商APP案例中,发现主线程被Binder通信阻塞,进一步排查发现是ContentProvider查询时没有使用异步加载。
对于常见的NullPointerException,除了看崩溃堆栈,还要关注设备状态:
bash复制adb logcat -b events | grep -E "am_crash|am_anr"
这个命令会输出崩溃时的内存状态和CPU负载。曾经有个内存泄漏案例,只有在系统内存低于20%时才会触发OOM崩溃,通过事件日志里的memFactor字段确认了这一点。
系统服务死锁是最难排查的问题之一。当看到这样的日志:
code复制W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in handler
立即执行以下命令收集证据:
bash复制adb shell cat /proc/sysrq-trigger -t l
adb shell dumpsys activity processes > deadlock.txt
第一个命令会触发内核打印所有CPU的调用栈,第二个命令保存服务状态。有次我们发现InputDispatcher线程持有了WindowManager的锁,而WindowManager又在等待InputDispatcher的消息,典型的ABBA死锁。
systrace是分析卡顿的神器,但很多人不会用它的高级功能:
bash复制python systrace.py -b 32768 -t 10 -o trace.html \
gfx input view wm am sm audio video camera
这个命令会采集10秒内关键系统服务的状态。参数-b 32768表示缓冲区大小,对于高负载设备要适当调大。上周用这个方法定位到一个SurfaceFlinger的VSync信号丢失问题,最终发现是GPU驱动超频导致。
当遇到SIGSEGV信号崩溃时,/data/tombstones/tombstone_XX文件就是我们的"验尸报告"。关键信息包括:
用addr2line定位代码位置:
bash复制aarch64-linux-android-addr2line -e /path/to/symbols/libnative.so 0x1234
对于堆破坏问题,需要在代码中增加调试信息:
c复制#define MEM_DEBUG
#ifdef MEM_DEBUG
#define malloc(size) debug_malloc(size, __FILE__, __LINE__)
#define free(ptr) debug_free(ptr, __FILE__, __LINE__)
#endif
这个技巧曾帮我找到一个只在夜间出现的野指针问题,原因是多线程环境下没有加锁的内存操作。
当内核崩溃时,第一时间保存pstore内容:
bash复制adb shell cat /sys/fs/pstore/console-ramoops > kernel_log.txt
配置pstore需要在设备树中添加:
dts复制reserved-memory {
ramoops@0x60000000 {
compatible = "ramoops";
reg = <0x0 0x60000000 0x0 0x400000>;
record-size = <0x4000>;
console-size = <0x200000>;
};
};
硬件看门狗触发后,需要用crash工具分析DDR dump:
bash复制crash vmlinux DDRCS0.bin --kaslr=0x5d880000
常用命令:
有次分析发现看门狗超时是因为中断被禁用超过20秒,最终定位到某个驱动在spin_lock_irqsave后没有及时释放。
建立系统化的排查流程比掌握具体工具更重要。我的经验是:
曾经有个只在特定机型上出现的蓝牙崩溃问题,通过对比不同内核版本的Oops信息,最终发现是DMA内存对齐的硬件差异导致。