在應(yīng)用開發(fā)中,我們常常會進(jìn)行日志打印或者debug調(diào)試,以此來分析運(yùn)行時(shí)的一些信息,便于發(fā)現(xiàn)bug和問題。Android Studio的Debug功能很好用,但是有時(shí)候有些情況下,就顯得不是那么快捷和便利。
比如
- 我們調(diào)試的點(diǎn)在應(yīng)用一打開的時(shí)候,很靠前,例如Application的onCreate方法中,以至于我們不能足夠快的設(shè)置進(jìn)程為debug模式
- 雖然上面的情況可以通過Android Studio的debug運(yùn)行來解決,但是如果項(xiàng)目很大的話,運(yùn)行起來也會比較耽誤時(shí)間
那么怎么解決上面的問題呢,其實(shí)只需要執(zhí)行一行命令即可
adb shell am set-debug-app -w com.example.jimmy.appdebugsample
其中
- set-debug-app 用來應(yīng)用為debug模式
- -w 意思為wait,在進(jìn)程啟動的時(shí)候,等待debugger進(jìn)行連接
-
com.example.jimmy.appdebugsample代表想要調(diào)試的應(yīng)用的包名或ApplicationId
執(zhí)行上面的命令,當(dāng)我們再次啟動目標(biāo)應(yīng)用時(shí),會得到這樣的畫面

然后,我們就會有足夠的時(shí)間,來使用Run—> Attach Debugger to Android Process 來綁定進(jìn)程debug。 綁定后對話框消失,下次啟動就是正常的啟動(沒有上面的對話框了)
那么一次debug不一定能解決問題,多次調(diào)試則在所難免,那么每次都要執(zhí)行這個(gè)命令么?
答案是可以,但是有更好的方式。即
adb shell am set-debug-app -w --persistent com.example.jishuxiaoheiwu.appdebugsample
上面的代碼和之前有所不同,表現(xiàn)在一個(gè)--persistent
- —persitent意思是持久的,意思是一直設(shè)置這個(gè)應(yīng)用為調(diào)試模式,即每次開啟(進(jìn)程創(chuàng)建)都會彈出對話框,即使卸載再安裝或者更新應(yīng)用
多次debug完成后,想要恢復(fù)正常的啟動:
adb shell am clear-debug-app
二、android調(diào)試工具addr2line使用:
1.將ndk中的arm-linux-androideabi-addr2line可執(zhí)行文件的路徑加入配置文件~/.bashrc中,例如:
export PATH=$PATH:~/dlna/android-ndk-r6b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin
2.使配置生效:
source ~/.bashrc
3.使用工具。例如:
arm-linux-androideabi-addr2line -C -f -e ~/workspace/DLNA/libs/armeabi/libctrlpt.so 0003deb4
其中,0003deb4為堆棧信息中pc的值。
使用addr2line追蹤自有動態(tài)庫(so文件)的bug,補(bǔ)充:
解決出現(xiàn) ??:0 , 沒法展示源代碼行數(shù)的問題
在Android.mk 文件中:
Java代碼
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wl,-Map=test.map -g
補(bǔ)充2個(gè)編譯參數(shù) -Wl,-Map=test.map -g .
增加gcc警告和調(diào)試標(biāo)志
arm-linux-androideabi-addr2line -C -f -e /項(xiàng)目目錄/obj/local/armeabi/libfaa_jni.so 0024362e
tip: 1,注意調(diào)試文件的位置在obj目錄下,并非libs目錄下生成的so文件
2,0024362e 為出錯的機(jī)制位置
還有:
在jni/目錄下增加Application.mk 文件, 修改為debug 模式,進(jìn)行調(diào)試 APP_OPTIM := debug
具體application.mk 文件的配置見: http://blog.csdn.net/weidawei0609/article/details/6561280
-----凡是backtrace下帶pc字樣的地址都可以用NDK中或linux下的arm-linux-androideabi-addr2line工具將地址映射成函數(shù)名字。----定位到具體位置
三、使用 GDB
GNU 項(xiàng)目調(diào)試程序 (GDB) 是常用的 Unix 調(diào)試程序。本頁詳細(xì)介紹了如何使用 gdb 調(diào)試 Android 應(yīng)用和進(jìn)程(面向平臺開發(fā)者)。對于第三方應(yīng)用開發(fā),請參閱調(diào)試您的應(yīng)用。
調(diào)試運(yùn)行中的應(yīng)用或進(jìn)程
要連接到已在運(yùn)行的應(yīng)用或本機(jī)守護(hù)進(jìn)程,請配合使用 gdbclient 和 PID。例如,要調(diào)試 PID 為 1234 的進(jìn)程,請運(yùn)行:
gdbclient 1234
此腳本會設(shè)置端口轉(zhuǎn)發(fā),在設(shè)備上啟動相應(yīng)的 gdbserver,在主機(jī)上啟動相應(yīng)的 gdb,配置 gdb 以找出符號,然后將 gdb 連接到遠(yuǎn)程 gdbserver。
調(diào)試本機(jī)進(jìn)程啟動
要在進(jìn)程啟動時(shí)對其進(jìn)行調(diào)試,請使用 gdbserver 或 gdbserver64(適用于 64 位進(jìn)程)。例如:
adb shell gdbserver :5039 /system/bin/MY_TEST_APP
輸出示例:
Process MY_TEST_APP created; pid = 3460
Listening on port 5039
接著,從 gdbserver 輸出內(nèi)容中找到應(yīng)用 PID,并在另一個(gè)終端窗口中使用:
gdbclient APP_PID
最后,在 gdb 提示處輸入 continue。
注意:如果您指定了錯誤的 gdbserver,將會收到?jīng)]任何幫助的錯誤消息(例如“Reply contains invalid hex digit 59”)。
調(diào)試應(yīng)用啟動
有時(shí),您需要在應(yīng)用啟動時(shí)對其進(jìn)行調(diào)試;例如在應(yīng)用發(fā)生崩潰時(shí),您需要逐步檢查代碼,以查看崩潰之前發(fā)生的情況。附加調(diào)試程序有時(shí)能解決問題,有時(shí)不能解決問題,因?yàn)閼?yīng)用可能會在您可以附加調(diào)試程序之前崩潰。logwrapper 方法(用于 strace 和 valgrind)不一定能解決所有的問題,因?yàn)閼?yīng)用可能沒有權(quán)限打開端口,而 gdbserver 會繼承這項(xiàng)限制。
要調(diào)試應(yīng)用啟動,請使用“設(shè)置”中的開發(fā)者選項(xiàng),指示應(yīng)用等待附加 Java 調(diào)試程序:
- 請依次轉(zhuǎn)到“設(shè)置”>“開發(fā)者選項(xiàng)”>“選擇調(diào)試應(yīng)用”,并從列表中選擇您的應(yīng)用,然后按等待調(diào)試程序。
- 啟動應(yīng)用,您可以從啟動器啟動,也可以在命令行中運(yùn)行以下命令來啟動:
am start -a android.intent.action.MAIN -n APP_NAME/.APP_ACTIVITY
- 等待應(yīng)用加載,然后等待系統(tǒng)顯示一個(gè)對話框提示您應(yīng)用正在等待附加調(diào)試程序。
- 正常附加
gdbserver/gdbclient,設(shè)置斷點(diǎn),然后繼續(xù)運(yùn)行該進(jìn)程。
要讓應(yīng)用實(shí)際運(yùn)行,請附加 Java 調(diào)試網(wǎng)絡(luò)協(xié)議 (JDWP) 調(diào)試程序,例如 Java 調(diào)試程序 (jdb):
adb forward tcp:12345 jdwp:XXX # (Where XXX is the pid of the debugged process.)
jdb -attach localhost:12345
調(diào)試崩潰的應(yīng)用或進(jìn)程
如果您希望 debuggerd 暫停崩潰的進(jìn)程,以便您可以附加 gdb,請?jiān)O(shè)置相應(yīng)的屬性:
//Android 7.0 Nougat and later.
adb shell setprop debug.debuggerd.wait_for_gdb true
//Android 6.0 Marshmallow and earlier.
adb shell setprop debug.db.uid 999999
在尋常崩潰輸出的結(jié)尾處,debuggerd 會提供有關(guān)如何使用以下命令來連接 gdb 的說明:
gdbclient PID
無符號調(diào)試
對于 32 位 ARM,如果您的指令中沒有符號,gdb 就不清楚自己正在反匯編哪個(gè)指令集(ARM 或 Thumb)。要指定缺少符號信息時(shí)選為默認(rèn)指令集的指令集,請?jiān)O(shè)置以下屬性:
set arm fallback-mode arm # or thumb
參考:
一個(gè)簡單實(shí)用的Android調(diào)試應(yīng)用技巧
android應(yīng)用崩潰的調(diào)試方法(c++ lib so文件庫崩潰)
GDB調(diào)試