在开发NDK的过程中,我们会发现,一旦程序出现异常,程序会直接闪退,而且不会有相关的日志,只会留下类似这样的一句话:
1
| A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 1656 (telife.jnistudy)
|
一旦遇到这样的错误信息,我们即找不到错误的原因,也找不到出错的地方,根本无从改起。
那要怎么办呢?
ndk-stack
ndk-stack
工具让您可以在堆叠追踪出现在 adb logcat 的输出中时过滤它们。 它还可以从源代码将共享库中的任意地址替换为对应的 <source-file>:<line-number>
值,从而更容易找出问题所在。
1
| adb logcat |library/android-ndk-r14b/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi
|
具体的错误信息:
1 2 3 4 5 6 7 8
| ********** Crash dump: ********** Build fingerprint: 'PAX/CB03/CB03:5.1.1/LMY47V/CB03_CH_V4.70_S:user/test-keys' pid: 3136, tid: 3136, name: telife.jnistudy >>> win.whitelife.jnistudy <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 Stack frame #00 pc 000009e8 /data/app/win.whitelife.jnistudy-1/lib/arm/libArray_test.so (_JNIEnv::GetIntArrayRegion(_jintArray*, int, int, int*)+31) Stack frame #01 pc 00000965 /data/app/win.whitelife.jnistudy-1/lib/arm/libArray_test.so (Java_win_whitelife_jnistudy_java_JavaHelper_setArray+64) Stack frame #02 pc 000a21b1 /system/lib/libart.so (art_quick_generic_jni_trampoline+32) Stack frame #03 pc 001d8ce9 /system/lib/libart.so (art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+132)
|
这样,你就可以看到在源文件具体哪里出现了错误。
异常处理
刚刚讲了如何在出现错误的时候将错误信息打印出来,那后面要讲如果是在调用java层代码时出现错误,该如何处理。我们知道,在java中调用出现错误时,程序会直接闪退。但是在native层调用java出现错误时,程序不会直接闪退,而是会走完整个函数。在java中我们可以通过try-catch来捕获异常进行处理,而在native中也有类似的方法来捕获异常。
ExceptionCheck
异常判断,可以通过该方法,判断在调用java代码之后是否出现异常。
ExceptionDescribe
打印错误信息,将错误信息打印到日志中。
ExceptionClear
将扔出的错误信息清除,这样程序不会在抛出错误。
ThrowNew
抛出java异常,将异常作为java异常抛出去。
1 2 3 4 5 6
| if(env->ExceptionCheck()){ env->ExceptionDescribe();//打印异常 env->ExceptionClear();//清除异常 jclass c=env->FindClass("java/lang/Exception"); env->ThrowNew(c,"出错了"); }
|