ndk

NDK学习笔记(四)

Posted by alonealice on 2017-02-08

在开发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,"出错了");
}