NDK学习笔记-JNI的异常处理与缓存策略

在使用JNI的时候,可能会产生异常,此时就需要对异常进行处理

异常处理

JNI抛出Throwable异常,在Java层可以用Throwable捕捉
而在C只有清空异常这种处理
但如果在JNI中通过ThrowNew抛出异常,则在Java曾可以捕获
例子(在native访问不存在的属性)
Java中声明native方法

public native void exception();

在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;");
	//检测是否发生Java异常
	jthrowable exception = (*env)->ExceptionOccurred(env);
	if (exception != NULL)
	{
		//清空异常信息
		(*env)->ExceptionClear(env);
		//抛出异常给Java层
		jclass exception_cls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
		(*env)->ThrowNew(env, exception_cls, "key0 is not invalid");
	}
}

此处访问了一个不存在的属性,通过ThrowNew将异常抛给Java处理
有时候需要在native中添加补救措施,这取决于实际的运用场景

因此在异常处理的时候,要保证Java能够正常运行

缓存策略

在多次获取同一个属性或对象的时候,使用缓存,可以有效减少属性和对象的内存占用

在使用的时候定义

定义一个static变量,保证其生成的只有一个,这样就节省了内存
局部static的生命周期随着程序而存在,作用于在其定义的代码块内

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_cached
(JNIEnv *env, jobject jobj)
{
	jclass cls = (*env)->GetObjectClass(env, jobj);
	//设置局部静态变量,保证其只会被赋值一次
	static jfieldID key_id = NULL;
	if (key_id == NULL)
	{
		key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
	}
}

初始化时候定义

初始化全局变量,动态库加载完成之后,立刻存储起来
那么在调用的时候就需要在加载完成立即调用

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

public native static void initIds();

在native中定义全局,然后对其进行赋值

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 @ 2019-04-05 22:50  cj5785  阅读(220)  评论(0编辑  收藏  举报