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是否能够捕获异常:
![](https://img.haomeiwen.com/i6288115/3a38f047c47209f5.png)
结果是: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());
}
}
![](https://img.haomeiwen.com/i6288115/42e49a00ff01549a.png)
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代码:
![](https://img.haomeiwen.com/i6288115/6d7bb2e49dd56b3d.png)