JNI异常处理和缓存策略
Posted developerLinwj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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异常处理》(http://blog.csdn.net/xyang81/article/details/45770551)
缓存策略
1、局部变量使用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"); }
以上是关于JNI异常处理和缓存策略的主要内容,如果未能解决你的问题,请参考以下文章