2.6 JNI异常处理
JNI函数在执行过程中会出现异常,其异常处理机制与Java和C++都不一样。JNI提供了两种检查异常的方法:
方法1 检查上一次 JNI函数调用的返回值是否为NULL。
方法2 通过调用JNI函数ExceptionOccurred()来判断是否发生异常。
检查到异常后必须予以处理。处理异常的方法也有两种:
Native方法可选择立即返回,这样异常就会在调用该Native方法的Java 代码中抛出。所以在Java代码中必须有捕获相应异常的代码,否则程序直接退出。
Native方法可以调用ExceptionClear()来清除异常,然后执行自己的异常处理代码。
JNI提供的检查和处理异常的函数如表2-5所示。
表2-5 JNI异常处理函数
注意 异常出现后,Native相关代码必须先检查清除异常,然后才能进行其他的 JNI 函数调用。当有异常未被清除时,只有以下JNI异常处理函数可被安全地调用:ExceptionOccurred()、ExceptionDescribe()?、ExceptionClear()、ExceptionDescribe()。
接下来,继续以Log系统为例讲解JNI的异常处理流程。先看以下代码:
static jboolean android_util_Log_isLoggable(JNIEnv* env,
jobject clazz, jstring tag, jint level)
{
……
if (tag== NULL) {//异常流程,直接退出
return false;
}
jbooleanresult=false;
const char*chars=env->GetStringUTFChars(tag, NULL);
if ((strlen(chars)+sizeof(LOG_NAMESPACE))>PROPERTY_KEY_MAX) {
……
// 异常流程,释放资源,抛出异常
env->ReleaseStringUTFChars(tag, chars);
jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
return false;
} else {//正常流程
result=isLoggable(chars, level);
}
env->ReleaseStringUTFChars(tag, chars);
return result;
}
从代码中并没有看到JNI异常处理函数的调用。我们接着分析jniThrowException方法。
该方法定义在JNIHelp.h中,并在JNIHelp.cpp中实现。代码如下:
extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg)
{
JNIEnv*e=reinterpret_cast(env);
if ((*env)->ExceptionCheck(e)) {//判断发生异常
scoped_local_refexception(env, (*env)->ExceptionOccurred(e));
(*env)->ExceptionClear(e);//得到异常引用并清除异常
if (exception.get() != NULL) {
char*text=getExceptionSummary(env, exception.get());
free(text);
}
}
原来JNIHelp.h中定义了jniThrowException,它只是把异常处理函数做了一个封装,方便使用而已。
下一节将通过应用层JNI使用的实例,把JNI相关内容再复习一遍。
【责任编辑:book TEL:(010)68476606】
点赞 0