##Android 开发中常见 Crash 的状况android
在 Android 开发中,程序 Crash 分三种状况:程序员
其中未捕获的异常根据 logcat 打印的堆栈信息很容易定位错误。bash
ANR错误也好查,Android规定,应用与用户进行交互时,若是5秒内没有响应用户的操做,则会引起ANR错误,并弹出一个系统提示框,让用户选择继续等待或当即关闭程序。并会在/data/anr目录下生成一个traces.txt文件,记录系统产生anr异常的堆栈和线程信息。composer
若是是闪退,这问题比较难查,一般是项目中用到了 NDK 引起某类致命的错误致使闪退。由于 NDK 是使用 C/C++ 来进行开发,熟悉 C/C++ 的程序员都知道,指针和内存管理是最重要也是最容易出问题的地方,稍有不慎就会遇到诸如内存地址访问错误、使用野指针、内存泄露、堆栈溢出、初始化错误、类型转换错误、数字除0等常见的问题,致使最后都是同一个结果:程序崩溃。它不会像在 Java 层产生的异常时弹出“xxx程序无响应,是否当即关闭”之类的提示框。当发生 NDK 错误后,logcat 打印出来的那堆日志根据看不懂,更别想从日志当中定位错误的根源。xss
首先,当 NDK 程序在发生 Crash 时,它会在路径 /data/tombstones/ 下产生致使程序 Crash 的文件 tombstone_xx。而且 Google 还在 NDK 包中为咱们提供了一系列的调试工具,例如 addr2line、objdump、ndk-stack。ide
##Linux 信号机制函数
在介绍 Tombstone 以前,咱们首先补充一个 Linux 信号机制的知识。工具
信号机制是 Linux 进程间通讯的一种重要方式,Linux 信号一方面用于正常的进程间通讯和同步,如任务控制(SIGINT, SIGTSTP,SIGKILL, SIGCONT,……);另外一方面,它还负责监控系统异常及中断。 当应用程序运行异常时, Linux 内核将产生错误信号并通知当前进程。 当前进程在接收到该错误信号后,能够有三种不一样的处理方式。oop
当 Linux 应用程序在执行时发生严重错误,通常会致使程序 crash。其中,Linux 专门提供了一类 crash 信号,在程序接收到此类信号时,缺省操做是将 crash 的现场信息记录到 core 文件,而后终止进程。ui
Crash 信号列表:
Signal | Description |
---|---|
SIGSEGV | Invalid memory reference. |
SIGBUS | Access to an undefined portion of a memory object. |
SIGFPE | Arithmetic operation error, like divide by zero. |
SIGILL | Illegal instruction, like execute garbage or a privileged instruction |
SIGSYS | Bad system call. |
SIGXCPU | CPU time limit exceeded. |
SIGXFSZ | File size limit exceeded. |
##Tombstone
Android Native 程序本质上就是一个 Linux 程序,所以当它在执行时发生严重错误,也会致使程序 crash,而后产生一个记录 crash 的现场信息的文件,而这个文件在 Android 系统中就是 tombstone 文件。tombstone 文件位于路径 /data/tombstones/ 下
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
Revision: '0'
ABI: 'x86'
pid: 1019, tid: 1019, name: surfaceflinger >>> /system/bin/surfaceflinger <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
eax a6265c06 ebx b7467d88 ecx b7631a22 edx a6265c06
esi 00000000 edi b6867140
xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b
eip b745a639 ebp bfcfc1e8 esp bfcfc150 flags 00010282
backtrace:
#00 pc 00006639 /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
#01 pc 00034b86 /system/lib/libsurfaceflinger.so
#02 pc 0003229e /system/lib/libsurfaceflinger.so
#03 pc 0002cb9c /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652)
#04 pc 000342f4 /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580)
#05 pc 0004eafb /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+411)
#06 pc 0004ce06 /system/lib/libgui.so (android::Surface::hook_queueBuffer(ANativeWindow*, ANativeWindowBuffer*, int)+38)
#07 pc 00014bc6 /system/lib/egl/libGLES_android.so
#08 pc 00017f73 /system/lib/egl/libGLES_android.so (eglSwapBuffers+163)
#09 pc 00015fdb /system/lib/libEGL.so (eglSwapBuffers+203)
#10 pc 000013ea /system/lib/hw/hwcomposer.x86.so
#11 pc 00034730 /system/lib/libsurfaceflinger.so
#12 pc 000256d4 /system/lib/libsurfaceflinger.so
#13 pc 00024bf4 /system/lib/libsurfaceflinger.so
#14 pc 000236fb /system/lib/libsurfaceflinger.so
#15 pc 0002338a /system/lib/libsurfaceflinger.so
#16 pc 0001e0ff /system/lib/libsurfaceflinger.so
#17 pc 0001d9ce /system/lib/libutils.so (android::Looper::pollInner(int)+926)
#18 pc 0001db73 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+67)
#19 pc 0001e561 /system/lib/libsurfaceflinger.so
#20 pc 00022ce7 /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::run()+39)
#21 pc 00000ca3 /system/bin/surfaceflinger
#22 pc 0001365a /system/lib/libc.so (__libc_init+106)
#23 pc 00000da8 /system/bin/surfaceflinger
stack:
bfcfc110 00000000
bfcfc114 b6839270
bfcfc118 00000000
bfcfc11c 00000000
bfcfc120 b68394e0
bfcfc124 00000002
bfcfc128 00000002
bfcfc12c b75d8185 /system/lib/libutils.so (android::RefBase::incStrong(void const*) const+53)
bfcfc130 b6839270
bfcfc134 bfcfc1e8 [stack]
bfcfc138 00000002
bfcfc13c a6265c06
bfcfc140 b7467d88 /system/lib/libui.so
bfcfc144 00000000
bfcfc148 b6867140
bfcfc14c b745a639 /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
#00 bfcfc150 b683af18
bfcfc154 bfcfc1e8 [stack]
bfcfc158 00000000
bfcfc15c 00000000
bfcfc160 00000000
bfcfc164 b683af18
bfcfc168 b75ec9c4 /system/lib/libutils.so
bfcfc16c b75d8285 /system/lib/libutils.so (android::RefBase::weakref_type::decWeak(void const*)+37)
bfcfc170 00000000
bfcfc174 00000000
bfcfc178 00000000
bfcfc17c 00000000
bfcfc180 b7642968 /system/lib/libsurfaceflinger.so
bfcfc184 bfcfc1e8 [stack]
bfcfc188 b6867140
bfcfc18c b7622b87 /system/lib/libsurfaceflinger.so
复制代码
tombstone 文件它主要由下面几部分组成:
pid: 1019, tid: 1019, name: surfaceflinger >>> /system/bin/surfaceflinger <<<
若是 pid 等于 tid ,那么就说明这个程序是在主线程中 Crash 掉的,name 的属性则表示 Crash 进程的名称以及在文件系统中位置。
复制代码
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
进程 Crash 的缘由是由于程序产生了段错误的信号,访问了非法的内存空间,而访问的非法地址是 0x4。
复制代码
addr2line addr2line -f -e libui.so 00006639
ndk-stack ndk-stack -sym obj/local/x86/ -dump ~/android-x86-debug-log/tombstone_01
objdump objdump -S -D libc.so > deassmble_libc.txt
## 源码快读
复制代码
bengin: com.android.server.am.ActivityManagerService.startObservingNativeCrashes