JNI--异常处理

2020-04-09  本文已影响0人  aruba

JAVA中可以使用try catch捕获异常,那么JNI中如果发生了异常会是什么现象呢?

我们在JAVA中定义native方法,并调用
package com.aruba.jniapplication;

/**
 * JNI 引用
 */
public class JniDemo6 {

    static {
        System.load("C:\\Users\\tyqhc\\source\\repos\\JniApplication\\x64\\Debug\\JniApplication.dll");
    }

    public native void getException();

    public static void main(String[] args) {
        JniDemo6 jniDemo6 = new JniDemo6();
        try {
            jniDemo6.getException();
        } catch (Exception e) {
            
        }
    }

}

编写C++代码,故意报一个异常
//获取异常
JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo5_getException
(JNIEnv* env, jobject jobj) {
    jclass jclz = env->GetObjectClass(jobj);
    jfieldID fid = env->GetFieldID(jclz,"key","Ljava/lang/String;");

    jstring jstr = (jstring)env->GetObjectField(jobj,fid);

    printf("c++ have exception \n");
}
很明显JniDemo6 中并没有key这个成员变量,编译后运行,看java是否能够捕获异常:
结果是:Java的try catch并捕获不到native方法的异常,还是报错了!但是C++代码还能往下执行,打印输出了信息!
JNI中异常处理有用自己的一套规则,需要JNI开发者在有可能产生异常的位置,调用env的ExceptionCheck方法,检查一下是否有异常
//获取异常
JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo6_getException
(JNIEnv* env, jobject jobj) {
    jclass jclz = env->GetObjectClass(jobj);
    jfieldID fid = env->GetFieldID(jclz,"key","Ljava/lang/String;");

    jstring jstr = (jstring)env->GetObjectField(jobj,fid);

    //检查是否有异常
    jboolean has_exception =  env->ExceptionCheck();
    if (has_exception) {
        //清空异常
        env->ExceptionClear();
    }

    printf("c++ have exception \n");
}
在执行Java代码
    public static void main(String[] args) {
        JniDemo6 jniDemo6 = new JniDemo6();
        try {
            jniDemo6.getException();
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
Java层已经不会报错了,但是也没有捕获异常,因为在native层已经将这个异常清掉了,我们需要手动创建一个异常告诉Java层,修改c++代码:
//获取异常
JNIEXPORT void JNICALL Java_com_aruba_jniapplication_JniDemo6_getException
(JNIEnv* env, jobject jobj) {
    jclass jclz = env->GetObjectClass(jobj);
    jfieldID fid = env->GetFieldID(jclz,"key","Ljava/lang/String;");

    jstring jstr = (jstring)env->GetObjectField(jobj,fid);

    //检查是否有异常
    jboolean has_exception =  env->ExceptionCheck();
    if (has_exception) {
        //清空异常
        env->ExceptionClear();
        jclass newExc = env->FindClass("java/lang/Exception");
        if(newExc != NULL)  env->ThrowNew(newExc,"c++ have exception to Java");
    }

    printf("c++ have exception \n");
}
在执行Java代码:
JNI的异常处理就到此结束了,总之有点坑爹,需要我们自己创建Java层的异常,Java才能捕获异常
上一篇 下一篇

猜你喜欢

热点阅读