Android Native Error / Crash 開發時調試分析

做者:仰簡, 連接:https://www.jianshu.com/p/9a5ba53b1e55java

1、前言

這篇文章我們來看看 Android Native Error / Crash 的問題在開發時如何調試分析。固然,只要能分析出緣由,天然就知道如何去解決啦。android

2、問題分析過程

下面的代碼,在運行時必然發生空指針 NULL 異常,從而 引起 App Native Crashgit

char *p = NULL;
char c = *p;

本地 / 開發時調試,很明顯就是咱們在開發時遇到程序發生的崩潰,或者這是一個能夠復現的問題。固然,也假設這個 so 是咱們本身的。那麼,這個時候咱們的 so 是 unstripped (未剝離版共享庫),簡單來講就是帶有 debug 時的符號表。github

下面,咱們先來看一下,上面的代碼在發生異常時,其報錯的大體異常 log 會是怎麼樣的。web

--------- beginning of crash
02-17 23:05:30.893 2610 2610 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 2610 (ly.com.crash)
02-17 23:05:30.998 1297 1297 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-17 23:05:30.999 1297 1297 F DEBUG : Build fingerprint: 'Android/sdk_phone_x86_64/generic_x86_64:6.0/MASTER/4174734:userdebug/test-keys'
02-17 23:05:30.999 1297 1297 F DEBUG : Revision: '0'
02-17 23:05:30.999 1297 1297 F DEBUG : ABI: 'x86_64'
02-17 23:05:30.999 1297 1297 F DEBUG : pid: 2610, tid: 2610, name: ly.com.crash >>> ly.com.crash <<<
02-17 23:05:30.999 1297 1297 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
02-17 23:05:31.003 1297 1297 F DEBUG : rax 0000000000000000 rbx 0000000012c53500 rcx 0000000000000000 rdx 000000000000000e
02-17 23:05:31.003 1297 1297 F DEBUG : rsi 00007fffbd76dee7 rdi 00007fffbd76df8f
02-17 23:05:31.003 1297 1297 F DEBUG : r8 0000000070799dd8 r9 0000000071d8c3b0 r10 00007fffbd76db80 r11 00007f722f0b21a0
02-17 23:05:31.003 1297 1297 F DEBUG : r12 0000000000000000 r13 0000000012cba100 r14 0000000012c53500 r15 0000000012c82100
02-17 23:05:31.003 1297 1297 F DEBUG : cs 0000000000000033 ss 000000000000002b
02-17 23:05:31.003 1297 1297 F DEBUG : rip 00007f722f0b21e0 rbp 00007fffbd76dfa0 rsp 00007fffbd76df30 eflags 0000000000010202
02-17 23:05:31.004 1297 1297 F DEBUG :
02-17 23:05:31.004 1297 1297 F DEBUG : backtrace:
02-17 23:05:31.004 1297 1297 F DEBUG : #00 pc 000000000000f1e0 /data/app/ly.com.crash-1/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)
02-17 23:05:31.004 1297 1297 F DEBUG : #01 pc 000000000070ba69 /data/app/ly.com.crash-1/oat/x86_64/base.odex (offset 0x2e2000) (java.lang.String ly.com.crash.MainActivity.stringFromJNI()+157)
02-17 23:05:31.004 1297 1297 F DEBUG : #02 pc 000000000070b950 /data/app/ly.com.crash-1/oat/x86_64/base.odex (offset 0x2e2000) (void ly.com.crash.MainActivity.onCreate(android.os.Bundle)+228)
02-17 23:05:31.004 1297 1297 F DEBUG : #03 pc 00000000734ab4bc /data/dalvik-cache/x86_64/system@framework@boot.oat (offset 0x1ed6000)
02-17 23:05:31.040 1297 1297 F DEBUG :
02-17 23:05:31.040 1297 1297 F DEBUG : Tombstone written to: /data/tombstones/tombstone_00
02-17 23:05:31.040 1297 1297 E DEBUG : AM write failed: Broken pipe

這個錯誤堆棧是從 logcat 裏面獲取的,其崩潰信息已經相對完善了。並且其中還有一句告知了更詳細的崩潰日誌被寫入到了 /data/tombstones/tombstone_00。咱們能夠藉助這個 /data/tombstones/tombstone_00 做更詳盡的分析。編程

而後,針對這個錯誤。從它的 backtrace 中咱們能夠看到其異常發生在咱們本身的 native-lib.so 中了,發生異常的錯誤棧爲:微信

#00 pc 000000000000f1e0  /data/app/ly.com.crash-2/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)

在 Android NDK 中給咱們提供了一個工具 ndk-stack ,利用 ndk-stack 就能夠輕鬆的將上面的異常棧轉換成可定位到源碼具體位置的可讀性更強的異常棧。app

使用 ndk-stack 時,咱們除了須要包含出問題時的異常棧的 log 以外,咱們還須要經過參數 -sym 來指定一個 unstripped 的 .so。通常在開發時,這個 so 的位置可能以下:編程語言

  • 若是你使用的是 ndk-build 來編譯的話,它可能位於 $PROJECT_PATH/app/build/intermediates/ndk-build/debug/obj/x86_64/***.so

若是使用的是 cmake 來編譯的話,它可能位於$PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64/***.so而對於指定異常 log 的方式,ndk-stack 也提供了兩種方式:編輯器

  • 將 logcat 直接做爲輸入:
adb logcat | ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64
  • 經過 -dump 指定一個包含異常日誌的文件
ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64 -dump foo.txt

上面的 $PROJECT_PATH 你須要替換成你本身的工程絕對路徑。

就這樣,經過上面一頓猛如虎的操做以後,咱們能夠獲得異常棧轉換後的可讀性更強的棧:

#00 0x000000000000f1e0 /data/app/ly.com.crash-2/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)
Java_ly_com_crash_MainActivity_stringFromJNI
/Users/ly/github/HelloCrash/app/src/main/cpp/native-lib.cpp:10:14

能夠看到,發生異常的地方在 native-lib.cpp 的 第 10 行第 14 列。

三思考 針對開發時,所發生的 native crash 來分析仍是很簡單的。那麼,當咱們的應用打成 release 包以後,發佈線上以後又該如何分析呢?

---END---


推薦閱讀:
Android&nbsp;Native&nbsp;Hook技術你知道多少?
JVM史上最最最完整深刻解析!萬字長文!
解決CoordinatorLayout的動畫抖動以及回彈問題
Java14新特性速覽!
2020 年編程語言盤點展望:Java 老兵不死,Kotlin 蓄勢待發


每個「在看」,我都當成真的喜歡

本文分享自微信公衆號 - 技術最TOP(Tech-Android)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索