JNI 异常捕获与处理

Posted null.....

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JNI 异常捕获与处理相关的知识,希望对你有一定的参考价值。

JNI 异常捕获与处理

jNI 异常捕获与处理,常见的 3 种情况:

  • native 层代码出错,native自己消费错误消息
  • java 层代码出错,导致 native 层调用出错
  • native 层代码没问题,调用 java 层代码出错

情况一:

native 层代码出错,native自己消费错误消息

native 层代码:

extern "C"
JNIEXPORT void JNICALL
Java_com_example_jni_activity_ExceptionActivity_nativeException1(JNIEnv *env, jobject thiz) {

    jclass j_class = env->GetObjectClass(thiz);

    //这行代码会报错!!!
    jfieldID j_id = env->GetFieldID(j_class, "name", "Ljava/lang/String;");
    //TODO 方式一
    //判断是否发生过异常
    jthrowable j_thr = env->ExceptionOccurred();
    if (j_thr) {
        LOGE("检测到异常");
        //清除异常
        env->ExceptionClear();
    }
}

辅助图:
在这里插入图片描述
假设现在 name 属性没有找到,name 就会报错,在这里使用:

env->ExceptionOccurred();

可以检测到 JNI 代码是否报错
如果报错,那么清除掉错误:

 env->ExceptionClear();

情况二

java 层代码出错,导致 native 层调用出错

native 层代码:

extern "C"
JNIEXPORT void JNICALL
Java_com_example_jni_activity_ExceptionActivity_nativeException2(JNIEnv *env, jobject thiz) {
    jclass j_class = env->GetObjectClass(thiz);
    //这行代码会报错!!!
    jfieldID j_id = env->GetFieldID(j_class, "name", "Ljava/lang/String;");

    //TODO 方式一
    //判断是否发生过异常
    jthrowable j_thr = env->ExceptionOccurred();
    //非 0 级 true
    if (j_thr) {
        LOGE("检测到异常");
        //清除异常
        env->ExceptionClear();

        //参数填写的是异常包名路径
        jclass null_class = env->FindClass("java/lang/NullPointerException");

        env->ThrowNew(null_class, "报错啦报错啦 NullPointerException!!");
    }
}

辅助图:
在这里插入图片描述
在调用 java 层代码的时候,发现 java 层代码会抛出一个 null 指针异常,那么在 JNI 层也要做相应的处理

和情况一 类似,先判断是否有过异常,如果有异常然后在清除异常,然后把异常信息返回给 java 层

//参数填写的是异常包名路径
jclass null_class = env->FindClass("java/lang/NullPointerException");

env->ThrowNew(null_class, "报错啦报错啦 NullPointerException!!");

findClass()解释:

  • 参数一:填写的是错误信息的路径:

运行结果为:
在这里插入图片描述

情况三

native 层代码没问题,调用 java 层代码出错

native层代码:

//TODO 方式三
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jni_activity_ExceptionActivity_nativeException3(JNIEnv *env, jobject thiz) {
    jclass j_class = env->GetObjectClass(thiz);

    jmethodID j_id = env->GetStaticMethodID(j_class, "showExpetcion", "()V");
    //调用 java 层的异常方法 ,走到这里会崩溃
    env->CallStaticVoidMethod(j_class, j_id);

    //检查是否会崩溃(可以理解为 判断 java 层是否抛出异常)
    if (env->ExceptionCheck()) {
        //输出描述错误信息
        env->ExceptionDescribe();
        //清除掉崩溃信息
        env->ExceptionClear();
    }
}

辅助图:

在这里插入图片描述
可以屏蔽掉 java 层报错异常的信息

完整代码

其他 JNI 文章:

第一篇:Android JNI 入门(含完整Demo)

第二篇:Android JNI 进阶(含完整 Demo)

第三篇:Android JNI QQ 搞怪语音实战 (含完整 Demo)

第四篇:Andoird JNI动态注册与 JNI 线程

原创不易,您的点赞就是对我最大的支持~

以上是关于JNI 异常捕获与处理的主要内容,如果未能解决你的问题,请参考以下文章

异常和TCP通讯

Android NDK开发篇:Java与原生代码通信(异常处理)

Android NDK开发篇:Java与原生代码通信(异常处理)

JNI - 在执行本机代码期间与目标 VM 断开连接

Java异常处理机制

java 异常捕获与异常处理