由于项目中有部分代码是通过c++实现的,在每次与底层对接都是非常痛苦的一件事。有时候是底层错误,有时候是JNI层的错误,一般来说JNI层出错后可以根据log看到崩溃的地方;而定位c++的错误可以通过NDK提供的三种工具定位:addr2line、objdump和ndk-stack,其中ndk-stack放在$NDK_HOME目录下,与ndk-build同级目录。addr2line和objdump在ndk的交叉编译器工具链目录下,下面是我本机NDK交叉编译器工具链的目录结构:
从上图的目录结构中可以看出来,NDK针对不同的CPU架构实现了多套相同的工具。所以在选择addr2line和objdump工具的时候,要根据你目标机器的CPU架构来选择。如果是arm架构,选择arm-linux-androidabi-4.8/4.9(一般选择高版本)。x86架构,选择x86-4.8/4.9。mipsel架构,选择mipsel-linux-android-4.8/4.9。如果不知道目标机器的CPU架构,把手机连上电脑,用adb shell cat /proc/cpuinfo可以查看手机的CPU信息。下图是我本机的arm架构工具链目录结构:
一般来说,可以通过backtrace查看奔溃的文件以及函数,但是在实际开发中一部分手机只有一句:
#signal有很多种 6、7、8、11等
Fatal signal 6 (SIGABRT) at 0x0000381f (code=-6), thread 15366 (包名)
看到只有一行的报错,这时候内心是奔溃的。。。
then,
所以首先使用ndk-stack协助我们获取底层崩溃的堆栈信息:
adb logcat | ndk-stack -sym ./obj/armeabi-v7a/你的lib名称.so
这个时候我们终于可以看到堆栈的地址了:
接着使用addr2line 方式获取奔溃信息:
直接使用arm-linux-androideabi-addr2line指令,需要配置系统的环境变量,链接http://blog.csdn.net/u011484134/article/details/54630241
arm-linux-androideabi-addr2line -C -f -e ./obj/armeabi-v7a/你的lib名称.so 000eea70
到目前为止,已经可以通过地址获取奔溃的堆栈(可准确获取函数以及错误的行数)。
最后还是要说说objdump方式,因为项目太大,获取的dump.log文件庞大,需要自己根据地址搜索奔溃的位置,嫌麻烦就没用这种方法。
arm-linux-androideabi-objdump -S -D ./obj/armeabi-v7a/你的lib名称.so > /Users/yidongjiang/Desktop/dump.log
注意:
- 上述用到的so为obj文件下的,不能使用libs文件中的so,否则将获取失败;
- 为了方便可以配置ndk的环境变量;