JNI引用,异常处理,缓存策略

引用类型:局部引用和全局引用
作用:在JNI中告知虚拟机何时回收一个JNI变量

局部引用

局部引用,通过NewLocalRef创建局部引用对象,DeleteLocalRef手动释放对象
1.访问一个很大的java对象,使用完之后,还要进行复杂的耗时操作
2.创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性

全局引用

共享(可以跨多个线程),手动控制内存使用
全局引用,通过NewGlobalRef创建局部引用对象,通过DeleteGlobalRef手动释放对象

弱全局引用

节省内存,在内存不足时可以是释放所引用的对象
创建:NewWeakGlobalRef,销毁:DeleteGlobalWeakRef
可以引用一个不常用的对象,如果为NULL,临时创建

异常处理

1.保证Java代码可以运行
2.补救措施保证C代码继续运行
JNI自己抛出的异常,在Java层通过Throwable可以捕获
用户通过ThrowNew抛出的异常,可以在Java层捕捉

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

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

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

    //对比属性值是否合法
    if (_stricmp(str, "super jason") != 0){
        //认为抛出异常,给Java层处理,java后面的代码可以继续执行
        jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
        (*env)->ThrowNew(env,newExcCls,"key's value is invalid!");
    }
}

缓存策略

static

//static jfieldID key_id 
JNIEXPORT void JNICALL Java_com_ccg_jni_JniTest_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, "key", "Ljava/lang/String;");
        printf("--------GetFieldID-------\n");
    }
}

初始化全局变量,动态库加载完成之后,立刻缓存起来

jfieldID key_fid;
jmethodID random_mid;
JNIEXPORT void JNICALL Java_com_ccg_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引用,异常处理,缓存策略)