Exception handling
Exception test examples:
public native void testException1(a);
public static void main(String[] args) {
JniTest test = new JniTest();
try {
test.testException();
System.out.println("Program cannot continue 1, this sentence will not be printed \n");
} catch (Throwable t) {
System.out.println("Catch an exception thrown by JNI (Throwable), this will be printed" + t.getMessage() + "\n");
}
System.out.println("The program continues to execute 2, and the sentence will be printed \n");
}
Copy the code
C code is as follows:
// Exception handling
JNIEXPORT void JNICALL Java_com_test_JniTest_testException1
(JNIEnv * env, jobject jobj){
jclass clz= (*env)->GetObjectClass(env, jobj);
// The property name was incorrectly written, and the property name was empty
jfieldID fid = (*env)->GetFieldID(env, clz, "key1"."Ljava/lang/String;");
// This throws an exception that Java can catch through Throwable
printf("C can run , this will print");
// It is possible to continue execution
jstring key = (*env)->GetObjectField(env, jobj, fid);
// The C program crashed
char* c_str = (*env)->GetStringUTFChars(env, key, NULL);
printf("C could not run , this will not print");
}
Copy the code
As you can see from the examples, the JNI layer throws an exception of the Error type. Java can catch the exception through Throwable or Error. After catching the exception, Java code can continue to execute.
In order to ensure that Java, C/C++ code can execute properly, you need to:
Manually clear ExceptionClear in the JNI layer to ensure that the code can run. Remedies ensure that C/C++ code continues to run. Such as:
// Exception handling
JNIEXPORT void JNICALL Java_com_test_JniTest_testException1
(JNIEnv * env, jobject jobj){
jclass clz = (*env)->GetObjectClass(env, jobj);
// The property name was incorrectly written, and the property name was empty
jfieldID fid = (*env)->GetFieldID(env, clz, "key1"."Ljava/lang/String;");
jthrowable err = (*env)->ExceptionOccurred(env);
if(err ! =NULL) {// Manually clear the exception information to ensure that the Java code can continue to execute
(*env)->ExceptionClear(env);
// Provide a remedy, such as getting another property
fid = (*env)->GetFieldID(env, clz, "key"."Ljava/lang/String;");
}
jstring key = (*env)->GetObjectField(env, jobj, fid);
char* c_str = (*env)->GetStringUTFChars(env, key, NULL);
}
Copy the code
The test code is as follows:
public static void main(String[] args) {
JniTest test = new JniTest();
try {
test.testException();
System.out.println("There is no exception in the program, this sentence will be printed \n");
} catch (Exception e) {
System.out.println("No exception thrown by JNI was caught, this sentence will not be printed" + e.getMessage() + "\n");
}
System.out.println("Program continues, this sentence will be printed \n");
}
Copy the code
The user can manually throw an exception through the ThrowNew function, which can also be caught by Java code:
// Exception handling
JNIEXPORT void JNICALL Java_com_test_JniTest_testException
(JNIEnv * env, jobject jobj){
jclass clz = (*env)->GetObjectClass(env, jobj);
// The property name was incorrectly written, and the property name was empty
jfieldID fid = (*env)->GetFieldID(env, clz, "key1"."Ljava/lang/String;");
jthrowable err = (*env)->ExceptionOccurred(env);
if(err ! =NULL) {// Manually clear the exception information to ensure that the Java code can continue to execute
(*env)->ExceptionClear(env);
// Provide a remedy, such as getting another property
fid = (*env)->GetFieldID(env, clz, "key"."Ljava/lang/String;");
}
jstring key = (*env)->GetObjectField(env, jobj, fid);
char* c_str = (*env)->GetStringUTFChars(env, key, NULL);
// The argument is not correct. The programmer throws an exception, which can be caught in Java
if (_stricmp(c_str,"efg") != 0){
jclass err_clz = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
(*env)->ThrowNew(env, err_clz, "key value is invalid!"); }}Copy the code
The test code is as follows:
public static void main(String[] args) {
JniTest test = new JniTest(a);try {
test.testException(a); System.out.println("JNI manually threw an exception, Java will not continue, this sentence will not be printed \n");
} catch (Exception e) {
System.out.println("Caught an exception that JNI manually threw, this sentence will be printed:" + e.getMessage() + "\n");
}
System.out.println("Program continues, this sentence will be printed \n");
}
Copy the code
Summary of Exception Handling
JNI throws an exception of the Error type, which Java can catch through Throwable or Error. After catching an exception, Java code can continue to execute. At the C layer, ExceptionClear is allowed to ensure that the Java code in the try continues to execute, and it is best to provide a remedy to ensure that the JNI layer code continues to run normally. Exceptions thrown manually by the user through ThrowNew can also be caught in the Java layer.