##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