Android项目集成breakpad及使用
集成
breakpad项目的github地址:github.com/google/brea…
把项目clone或者download下来,然后本地编译成so库或者通过项目集成进去;
初始化
在jni/breakpad/ 下添加 breakpad.cpp 文件,内容:
extern "C" JNIEXPORT void JNICALL
Java_com_example_breakpaddemo_MainActivity_breakpadInit(
JNIEnv *env,
jobject /* this */, jstring dump_path) {
const char *path = env->GetStringUTFChars(dump_path, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
static google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1);
env->ReleaseStringUTFChars(dump_path, path);
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
在java层通过jni调用Java_com_example_breakpaddemo_MainActivity_breakpadInit方法,path为log存放的路径
public static void initBreakpad(String path){
initBreakpadNative(path);
}
private static native void initBreakpadNative(String path);
写一段native报错代码 crash.cpp
/**
* 引起 crash
*/
void Crash() {
volatile int *a = (int *) (NULL);
*a = 1;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_breakpaddemo_MainActivity_crash(JNIEnv *env, jobject obj) {
Crash();
}
添加一个按钮,点击后通过jni调用crash方法
findViewById(R.id.crash_btn)
.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
crash();
}
});
public native void crash();
分析dmp文件
使用 minidump_stackwalk 工具把 dmp 文件生成堆栈的 log 信息
./minidump_stackwalk ***.dmp > crash.txt
如果不想自己编译生成 minidump_stackwalk 工具,可以使用 Android Studio 自带的 minidump_stackwalk 工具,路径在AS的安装路径下的 bin/lldb/bin 下
再来看看生成的 crash.txt
Thread 0 (crashed)//出现crash的线程
0 libcrash-lib.so + 0x650//发生crash的so文件和寄存器信息
x0 = 0x00000072b8a41300 x1 = 0x0000007fcb3ed354
x2 = 0x0000000000000000 x3 = 0x00000072b8ac7a00
x4 = 0x0000007fcb3ed7c8 x5 = 0x00000072b75e4f91
使用 ndk 中提供的 addr2line 来根据地址进行符号反解,addr2line 的路径:android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/ 目录下,请根据操作系统找对应的目录。
arm-linux-androideabi-addr2line -f -C -e
//发生crash的so库路径
../build/intermediates/transforms/mergeJniLibs/debug/0/lib/arm64-v8a/libcrash-lib.so 0x650
//打印结果
Crash();
总结
对于native崩溃报错的异常捕获,显然会比较麻烦,所以得付出一些耐心。本人也是第一次尝试,所以记录一下,有什么不对的地方,还望谅解,希望共勉。 对于NDK开发,还不是很熟悉,希望以后能够积累,学习完善对于NDK开发的一些知识。