Android Native crash 具有上下文不全、出错信息模糊、难以捕捉等特点,比 java crash 更难修复。
程序崩溃
- Unix-like系统中,崩溃都是编程错误或者硬件错误相关的,如除零、段地址错误等。
- 异常发生时,CPU通过异常中断的方式,触发异常处理流程。不同的处理器,有不同的异常中断类型和中断处理方式。
- linux把这些中断处理,统一为信号量。
- 信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号。
常见信号量
指针使用不当:
- 空指针。
- (char*)malloc(len + 1)),申请空间大小时,要加1,并且最后一个字节值置为0,表示字符串结尾。动态申请的内存,用完后要及时free掉,避免内存泄露
- msg = strcat(msg, "\r\n"),使用此方法时,msg的大小要足够大,能够容纳下,自身长度加上追加内容的长度
局部引用与全局引用:
JNI WARNING: 0x40538d98 is not a valid JNI reference
这个错误比较好解决。用NewGlobalRef将其转换成全局引用
FindClass仅返回局部引用, 需将其转换成全局引用:
jclass stringClass = (*env)->FindClass(env, "java/lang/String");
strClass = (*env)->NewGlobalRef(env, stringClass);
NewStringUTF仅返回局部引用.需将其转换成全局引用:
jstring coding = (*env)->NewStringUTF(env, "utf-8");
strencoding = (*env)->NewGlobalRef(env, coding);
ndk-stack
ndk-stack 工具让您可以在堆叠追踪出现在adb logcat
的输出中时过滤它们。 它还可以从源代码将共享库中的任意地址替换为对应的 <source-file>:<line-number> 值,从而更容易找出问题所在。
adb logcat | $NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi
您也可以使用 -dump 选项将 logcat 指定为输入文件。例如:
adb logcat > /tmp/foo.txt
$NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi -dump foo.txt
nm查看符号表
列出.o .a .so中的符号信息,包括诸如符号的值,符号类型及符号名称等,可以用于调试native方法找不到的问题。
nm -D hello.so
参数 | 描述 |
---|---|
A | Global absolute 符号 |
a | Local absolute 符号 |
B | Global bss 符号 |
b | Local bss 符号 |
D | Global data 符号 |
d | Local data 符号 |
f | 源文件名称符号 |
T | Global text 符号 |
t | Local text 符号 |
U | 未定义符号 |
参考:
https://zhuanlan.zhihu.com/p/27834417?group_id=868422576001671168
https://developer.android.com/ndk/guides/ndk-stack.html
http://www.cnblogs.com/wangkangluo1/archive/2012/07/02/2572438.html