异常:程序在运行期间没有按照正常的程序逻辑执行,在执行过程当中出现了某种错误,导致程序崩溃。
作用: 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");
}