JNI异常处理和缓存策略

异常:程序在运行期间没有按照正常的程序逻辑执行,在执行过程当中出现了某种错误,导致程序崩溃。

作用: 1、保证Java代码可以运行

2、补救措施保证C代码继续运行

由于JNI自己抛出的异常,在Java层无法被捕捉,只能在C层清空。而用户通过ThrowNew抛出的异常,可以在Java层捕捉。

public class MyException {
	
	public native void exeception();
	
	private String name = "xiaoming";
	
	public static void main(String[] args) {
		MyException m = new MyException();
		try {
			m.exeception();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("nihao");
	}
	
	//加载动态库
	static {
		System.loadLibrary("ConsoleApplication1");
	}

}

复制代码

native方法实现

JNIEXPORT void JNICALL Java_com_lwj_test_MyException_exeception
(JNIEnv *env, jobject jobj){
	jclass cls = (*env)->GetObjectClass(env, jobj);
	jfieldID fid = (*env)->GetFieldID(env, cls, "myname", "Ljava/lang/String;");
	//检测是否发生Java异常
	jthrowable exception = (*env)->ExceptionOccurred(env);
	if (exception != NULL){
		//让Java代码可以继续运行
		//清空异常信息
		(*env)->ExceptionClear(env);

		//补救措施
		fid = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
	}

	//获取属性的值
	jstring jstr = (*env)->GetObjectField(env, jobj, fid);
	char *str = (*env)->GetStringUTFChars(env, jstr, NULL);

	//对比属性值是否合法
	if (_stricmp(str, "xiaoming2") != 0){
		//认为抛出异常,给Java层处理
		jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
		(*env)->ThrowNew(env, newExcCls, "key's value is invalid!");
	}
}
复制代码

关于更加详细的异常处理,大家可以参考这篇文章:《JNI/NDK开发指南(十一)——JNI异常处理

缓存策略

局部变量使用static jfieldID key_id

Java类:

public class MyException {
	
	public native void cached();
	
	private String name = "xiaoming";
	
	public static void main(String[] args) {
		MyException m = new MyException();
		for(int i = 0;i< 10;i++) {
			m.cached();
		}
	}
	
	//加载动态库
	static {
		System.loadLibrary("ConsoleApplication1");
	}

}
复制代码

native实现

JNIEXPORT void JNICALL Java_com_lwj_test_MyException_cached
(JNIEnv *env, jobject jobj){
	jclass cls = (*env)->GetObjectClass(env, jobj);
	//获取jfieldID只获取一次
	//局部静态变量
	static jfieldID key_id = NULL;
	if (key_id == NULL){
		key_id = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
		printf("--------GetFieldID-------\n");
	}
}
复制代码

从结果中看出只获取一次。

2、全局变量

//初始化全局变量,动态库加载完成之后,立刻缓存起来
jfieldID key_fid;
jmethodID random_mid;
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_initIds(JNIEnv *env, jclass jcls){	
	key_fid = (*env)->GetFieldID(env, jcls, "key", "Ljava/lang/String;");
	random_mid = (*env)->GetMethodID(env, jcls, "genRandomInt", "(I)I");
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值