一录淡、簡介
在開發(fā)APP時一定會遇到程序異常退出的情況捌木,有時相對于解決問題,發(fā)現(xiàn)定位問題更加的困難和重要嫉戚。這里就需要一個功能強大的異常捕獲框架——BreakPad
Android的崩潰大體可分為以下三種:
- java層異常
- Native層異常
- ANR程序無響應(yīng):I/O刨裆、CPU或者大量GC導(dǎo)致的
對于以上三種情況澈圈,Native的異常捕獲定位比較困難。需要對操作系統(tǒng)等底層有很深入的了解帆啃,以及一些極端情況的考慮(如日志生成失敗導(dǎo)致的破壞了原來的崩潰現(xiàn)場)瞬女。才能制定一個優(yōu)秀的異常捕獲框架,但這也讓BreakPad的代碼量增加了努潘。
二诽偷、window下使用BreakPad
1)、下載BreakPad源碼
1疯坤、利用git等方式下載BreakPad源碼报慕,需要使用該編譯源碼生成工具,以及用到以上的JNI文件压怠。
2卖子、下載的頭文件中會缺少一個文件夾,會導(dǎo)致配置編譯的時候出現(xiàn)錯誤刑峡,這個需要手動的下載。這個可以在GitHub中下載
2)玄柠、配置編譯源碼
1突梦、環(huán)境準備
需要準備Linux系統(tǒng)和Make,我這里用的是ubantu-16-04-3版本羽利、Make-4.1宫患、XShell、共享工具
2这弧、編譯
-
1娃闲、將下載的文件放置到Linux共享文件中(或用git下載到一個目錄中)
image.png -
2、配置編譯
利用XShell配置breakpad文件夾下面中的configure文件匾浪,并make編譯皇帮。命令:./configure && make
minidump_stackwalk
完成后在processor目錄下會有個minidump_stackwalk文件,之后會使用蛋辈。
3)属拾、使用Breakpad
下載的BreakPad源碼會有JNI文件,利用該文件單獨放置一個模塊中冷溶,官方的例子中使用的是makefile,這里改用的是make編譯渐白。可以直接將GitHub中的breakpad下載使用逞频。
public class BreakpadInit {
static {
System.loadLibrary("breakpad-core");
}
public static void initBreakpad(String path){
initBreakpadNative(path);
}
private static native void initBreakpadNative(String path);
}
接下來使用breakpad就很簡單了纯衍,直接在初始化BreakPad庫的時候配置一個文件夾,該文件夾是存放之后生成的日志文件苗胀。
三襟诸、定位問題
- 1瓦堵、官方給出的Native奔潰例子如下:
#include <stdio.h>
#include <jni.h>
/**
* 引起 crash
*/
void Crash() {
volatile int *a = (int *) (NULL);
*a = 1;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_dodola_breakpad_MainActivity_crash(JNIEnv *env, jobject obj) {
Crash();
}
奔潰后,取出生成的奔潰日志励堡。我這里的日志名改成了t.dmp
- 2谷丸、使用minidump_stackwalk
在processor目錄下,執(zhí)行./minidump_stackwalk t.dmp > crash.txt
之后會生成一個crash.txt的日志文件应结。
Operating system: Android
0.0.0 Linux 4.4.21-perf-g6679372 #1 SMP PREEMPT Tue Jan 23 00:40:47 CST 2018 aarch64
CPU: arm64
8 CPUs
GPU: UNKNOWN
Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 libcrash-lib.so + 0x5e0
x0 = 0x0000007f7463e180 x1 = 0x0000007ffe09eb34
x2 = 0x0000000000000000 x3 = 0x0000007f74696a00
x4 = 0x0000007ffe09efa8 x5 = 0x0000007f58bbf506
x6 = 0x00000000001b9ded x7 = 0x0000000012c7cce8
x8 = 0x0000000000000001 x9 = 0x0000000000000000
x10 = 0x375abb98f10f9542 x11 = 0x0000000000000000
x12 = 0x0000000000000000 x13 = 0x0000000000430000
x14 = 0x0000000000000000 x15 = 0x0000007f745fc7d0
x16 = 0x0000007f73024fe8 x17 = 0x0000007f730145cc
x18 = 0x00000000000000af x19 = 0x0000007f74696a00
x20 = 0x0000007f7404d350 x21 = 0x0000007f74696a00
x22 = 0x0000007ffe09eddc x23 = 0x0000007f58bbf506
x24 = 0x0000000000000004 x25 = 0x375abb98f10f9542
x26 = 0x0000007f74696a98 x27 = 0x0000007f74690600
x28 = 0x375abb98f10f9542 fp = 0x0000007ffe09eb10
lr = 0x0000007f73014604 sp = 0x0000007ffe09eaf0
pc = 0x0000007f730145e0
Found by: given as instruction pointer in context
1 libcrash-lib.so + 0x600
fp = 0x0000007ffe09ebf8 lr = 0x0000007f58cfda94
sp = 0x0000007ffe09eb20 pc = 0x0000007f73014604
Found by: previous frame's frame pointer
2 base.odex + 0x2f9a90
fp = 0x0000007ffe09ecf0 lr = 0x0000007f7405af54
sp = 0x0000007ffe09ec08 pc = 0x0000007f58cfda94
Found by: previous frame's frame pointer
這里面有奔潰的位置:libcrash-lib.so + 0x5e0
使用的CPU架構(gòu):arm64
對于Crash Reason可以參考如下對應(yīng)表:
對應(yīng)上面的Native崩潰刨疼,可以看出崩潰的原因是“地址無效”導(dǎo)致的。
- 3鹅龄、使用addr2line
在SDK中toolchain交叉編譯工具鏈中揩慕,有個 aarch64-linux-android-addr2line.exe可執(zhí)行文件進行符號解析,這樣就可以將之前生成的crash.txt文件定位到哪一行的問題扮休。
這里執(zhí)行的命令:
aarch64-linux-android-addr2line.exe -f -C -e
D:\F\project\self\github\AndroidAdvanceWithGeektime\Chapter01\sample\build\intermediates\transforms\mergeJniLibs\debug\0\lib\arm64-v8a\libcrash-lib.so 0x5e0
這里需要錯誤的so文件和crash.txt中報錯對的偏移地址 0x5e0和addr2line.exe
這里就可以定位到是這個so庫中的Crash方法迎卤、第十行出現(xiàn)的問題。