我有JNI级别的代码。它可以抛出异常。代码是:
#include "JavaGlueClass.h"
#include <stdio.h>
#include <windows.h>
#include <string.h>
jint throwNoClassDefError(JNIEnv *env, const char *message)
{
jclass exClass;
char *className = (char *) "java/lang/NoClassDefFoundError" ;
exClass = env->FindClass(className);
if ( exClass != NULL ) {
return env->ThrowNew(exClass, message);
}
//free the local ref
env->DeleteLocalRef(exClass);
}
void throwGetFieldIDException(JNIEnv *env)
{
const char *className = "GetFieldIDException";
jclass exClass = env->FindClass(className);
if (exClass == NULL) {
throwNoClassDefError(env, className);
} else {
env->ThrowNew(exClass, "GetFieldIDException message");
}
env->DeleteLocalRef(exClass);
printf("printprint");
}
JNIEXPORT jobject JNICALL Java_JavaGlueClass_test(JNIEnv *env, jobject obj)
{
jmethodID constructor;
jobject object;
jclass clazz;
jfieldID fid;
jstring stringField;
clazz = env->FindClass("Information");
if (clazz == 0) {
printf("error while finding class");
throwNoClassDefError(env, "no such class");
} else {
//create object throuht constructor
constructor = env->GetMethodID(clazz, "<init>", "()V");
object = env->NewObject(clazz, constructor);
// set private value1 field
stringField = env->NewStringUTF("str1");
//fid = env->GetFieldID(clazz,"value1","Ljava/lang/String;");
fid = NULL;
if (fid == NULL) {
throwGetFieldIDException(env, "error with value1 field.");
//return NULL;
}
env->SetObjectField(object, fid, stringField);
//set private value2 field
fid = env->GetFieldID(clazz,"value2","I");
if (fid == NULL) {
throwGetFieldIDException(env, "error with value1 field.");
//return NULL;
}
env->SetIntField(object, fid, 1);
// set private value3 field
stringField = env->NewStringUTF("str2");
fid = env->GetFieldID(clazz,"value3","Ljava/lang/String;");
if (fid == NULL) {
throwGetFieldIDException(env, "error with value1 field.");
//return NULL;
}
env->SetObjectField(object, fid, stringField);
//set private value4 field
fid = env->GetFieldID(clazz,"value4","I");
if (fid == NULL) {
throwGetFieldIDException(env, "error with value1 field.");
//return NULL;
}
env->SetIntField(object, fid, 2);
printf("end of cpp function");
return object;
}
}
Java_JavaGlueClass_test函数创建自定义Information类的对象。每次我设置类字段时,都会检查“fid”是否为NULL。 我读到了有关异常的JNI异常。我发现将抛出的第一个异常将代码流移动到Java级别(而不是JNI级别)。但是在JNI级别的异常之后的其余代码呢?据我了解,它将被执行。 是否有可能在第一次异常后抛出第二个,第三个等异常?抛出异常后我应该返回NULL或其他东西,以便JNI级别的其余代码不会被执行吗?
答案 0 :(得分:6)
通过JNI引发的挂起异常(例如,通过调用ThrowNew)不会立即中断本机方法执行。这与Java编程语言中的异常行为有所不同。当Java编程语言抛出异常时,虚拟机会自动将控制流传输到与异常类型匹配的最近的封闭try / catch语句。然后,虚拟机清除挂起的异常并执行异常处理程序。相反,JNI程序员必须在发生异常后明确实现控制流程。