NDK Learning Notes-JNI exception handling and caching strategy

Keywords: Java Attribute

When using JNI, exceptions may occur, and exceptions need to be handled.

exception handling

JNI throws Throwable exceptions that can be captured at the Java layer with Throwable
In C, only the exception is cleared.
But if an exception is thrown through ThrowNew in JNI, it could have been caught in Java
Example (accessing non-existent attributes in native)
Declaring native methods in Java

public native void exception();

Processing in native

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_exception
(JNIEnv *env, jobject jobj)
{
	jclass cls = (*env)->GetObjectClass(env, jobj);
	jfieldID fid = (*env)->GetFieldID(env, cls, "key0", "Ljava/lang/String;");
	//Detecting Java exceptions
	jthrowable exception = (*env)->ExceptionOccurred(env);
	if (exception != NULL)
	{
		//Clean up abnormal information
		(*env)->ExceptionClear(env);
		//Throw exceptions to the Java layer
		jclass exception_cls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
		(*env)->ThrowNew(env, exception_cls, "key0 is not invalid");
	}
}

Here, a non-existent property is accessed and exceptions are thrown to Java processing through ThrowNew
Sometimes remedies need to be added to native, depending on the actual application scenario

So when dealing with exceptions, make sure Java works properly.

Cache policy

When the same attribute or object is acquired many times, the use of caching can effectively reduce the memory occupancy of the attribute and object.

Definition in use

Define a static variable to ensure that it generates only one variable, thus saving memory
The life cycle of a local static exists with the program and acts on the block of code it defines.

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_cached
(JNIEnv *env, jobject jobj)
{
	jclass cls = (*env)->GetObjectClass(env, jobj);
	//Set local static variables to ensure that they are assigned only once
	static jfieldID key_id = NULL;
	if (key_id == NULL)
	{
		key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
	}
}

Definition at initialization time

Initialize global variables and store them immediately after loading the dynamic library
Then the call needs to be called immediately after loading.

static {
		System.loadLibrary("JNITest");
		initIds();
}

public native static void initIds();

Define the global in native and assign it

jfieldID key_fid;
jmethodID random_mid;
JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_initIds
(JNIEnv *env, jclass jcls)
{
	key_fid = (*env)->GetFieldID(env, jcls, "key", "Ljava/lang/String;");
	random_mid = (*env)->GetMethodID(env, jcls, "getRandomInt", "(I)I");
}

Posted by tarleton on Fri, 05 Apr 2019 09:48:30 -0700