Appearance
native-crash-breakpad
1. 实验目标
演示 Android Native 层崩溃的完整链路(对应 docs/07-performance-testing-debug/12):
- 在 native 代码里故意触发 SIGSEGV(空指针解引用),观察 tombstone 生成
- 用带符号的
.so配合ndk-stack/minidump_stackwalk(Breakpad)把地址还原成函数名 + 行号 - 对照 Java 层
UncaughtExceptionHandler与 native 崩溃的捕获差异
本实验给出 native 触发代码 + 还原命令(见「7. 关键源码」);完整编译需要 NDK 工程,暂不接入 Android Host 构建。
2. 工程要点
- Native 崩溃由 signal 投递:
SIGSEGV(11) /SIGABRT(6) /SIGBUS(7);debuggerd抓取生成/data/tombstones/tombstone_xx - tombstone 只含偏移地址,需
(objdump/ndk-stack) + 带符号 so还原符号 - Breakpad:编译期注入
libbreakpad,崩溃时写minidump,离线用minidump_stackwalk还原(适合发版后远程堆栈)
3. 运行方式
bash
# 1) 触发并抓 tombstone(native 空指针)
adb shell kill -11 <pid> # 或运行触发 SIGSEGV 的 demo
adb shell cat /data/tombstones/tombstone_00 | head -60
# 2) 用 ndk-stack 还原(需 NDK 与未 strip 的 so)
ndk-stack -sym app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a/ \
-dump tombstone_00
# 3) Breakpad 离线还原
minidump_stackwalk crash.dmp symbols/ > crash.txt4. 预期现象
SIGSEGV后进程退出,logcat出现Fatal signal 11 (SIGSEGV),/data/tombstones新增一条- tombstone 中
#00 pc 0000xxxx经ndk-stack还原为native_crash_demo.cpp:42(函数 + 行号) - 未带符号的 so 只能看到地址,看不到函数名 → 强调发版保留
unstripped .so
5. 常见误区
| 误区 | 实际情况 |
|---|---|
| Java 的 try/catch 能兜住 native 崩溃 | 不能,native 崩溃直接 signal,绕开 JVM 异常体系 |
| 发版 so 带符号更方便排查 | 发版应 strip,单独归档 unstripped so 供还原(体积与安全) |
| tombstone 自带函数名 | 默认只有地址,必须配符号表才会显示符号 |
6. 对应知识库文档
7. 关键源码
cpp
// native_crash_demo.cpp —— 故意触发 SIGSEGV(空指针解引用)
extern "C" JNIEXPORT void JNICALL
Java_com_example_NativeCrash_triggerSigsegv(JNIEnv*, jobject) {
int* p = nullptr;
*p = 42; // 第 42 行:解引用空指针 → SIGSEGV
}bash
# build.gradle 保留 unstripped so 供还原
android {
buildTypes {
debug { ndk { debugSymbolLevel = "FULL" } }
}
}接入状态
✅ 已接入 Android 宿主 App:对应 NativeCrashBreakpadActivity,从 MainActivity → 「打开 Native Crash (SIGSEGV) 实验室」进入。点按钮即向自身进程发 SIGSEGV(11) 产生真实 tombstone,无需 NDK/JNI。可用 adb logcat -b crash 观察。