JNI 程序中的异常分为以下几种:
很多 JNIEnv 中的函数都会抛出异常,处理方法大体上是一致的:
接着我们来看一个例子:
Java 层:
public native void exceptionTest();
//调用
try {
exceptionTest();
} catch (Exception e) {
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
//查找的类不存在,返回 NULL;
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/xxx");
if (clazz == NULL) {
return; //return 后,jvm 会向 java 层抛出 ClassNotFoundException
}
}
执行后的 log:
java.lang.ClassNotFoundException: Didn't find class "com.yuandaima.myjnidemo.xxx"
说明,java 层捕获到了异常
Native 回调 Java 层方法,被回调的方法抛出异常。这样情况下一般有两种解决办法:
Java 层:
//执行这个方法会抛出异常
private static int exceptionMethod() {
return 20 / 0;
}
//native 方法,在 native 中,会调用到 exceptionMethod() 方法
public native void exceptionTest();
//Java 层调用
try {
exceptionTest();
} catch (Exception e) {
//这里处理异常
//一般是打 log 和弹 toast 通知用户
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
//调用 java 层会抛出异常的方法
jmethodID static_method_id = env->GetStaticMethodID(clazz, "exceptionMethod", "()I");
if (NULL == static_method_id) {
return;
}
//直接调用,发生 ArithmeticException 异常,传回 Java 层
env->CallStaticIntMethod(clazz, static_method_id);
env->DeleteLocalRef(clazz);
}
有的异常需要在 Native 处理,这里又分为两类:
接着我们看下示例:
Java 层:
//执行这个方法会抛出异常
private static int exceptionMethod() {
return 20 / 0;
}
//native 方法,在 native 中,会调用到 exceptionMethod() 方法
public native void exceptionTest();
//Java 层调用
try {
exceptionTest();
} catch (Exception e) {
//这里处理异常
//一般是打 log 和弹 toast 通知用户
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
jthrowable mThrowable;
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
jmethodID static_method_id = env->GetStaticMethodID(clazz, "exceptionMethod", "()I");
if (NULL == static_method_id) {
return;
}
env->CallStaticIntMethod(clazz, static_method_id);
//检测是否有异常发生
if (env->ExceptionCheck()) {
//获取到异常对象
mThrowable = env->ExceptionOccurred();
//这里就可以根据实际情况处理异常了
//.......
//打印异常信息堆栈
env->ExceptionDescribe();
//清除异常信息
//如果,异常还需要 Java 层处理,可以不调用 ExceptionClear,让异常传递给 Java 层
env->ExceptionClear();
//如果调用了 ExceptionClear 后,异常还需要 Java 层处理,我们可以抛出一个新的异常给 Java 层
jclass clazz_exception = env->FindClass("java/lang/Exception");
env->ThrowNew(clazz_exception, "JNI抛出的异常!");
env->DeleteLocalRef(clazz_exception);
}
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(mThrowable);
}
阅读量:2019
点赞量:0
收藏量:0