引用的类型:局部引用、全局引用和 弱全局引用
对于JNI引用类型可以参考这篇文章
引用的作用:在JNI中告知虚拟机何时回收一个JNI变量。
局部引用
局部引用:通过NewLocalRef和各种JNI接口创建(FindClass、NewObject、GetObjectClass和NewCharArray等)。局部引用会在C/C++代码执行完成之后自动释放(可以回收)。 但是,有时候我们需要手动去释放(调用DeleteLocalRef释放): 1、访问一个很大的Java对象,使用完之后,还要进行复杂的耗时操作 2、创建了大量的局部引用,占用了太多的内存,而且这些布局引用跟后面的操作没有关联性
jclass cls = (*env)->FindClass(env, "java/util/Date"); jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "", "()V"); //实例化Date对象 jobject obj = (*env)->NewObject(env, cls, constructor_mid); //Date对象数组 jobjectArray jobj_arr = (*env)->NewObjectArray(env, 5, cls, obj); //提前释放,不要占用内存太久 //告诉虚拟机垃圾回收器,可以回收这些对象 (*env)->DeleteLocalRef(env, obj); (*env)->DeleteLocalRef(env, jobj_arr);复制代码
需要注意的是:局部引用不能在多个线程间传递
全局引用
局部引用:调用NewGlobalRef
基于局部引用创建,会阻GC回收所引用的对象。需要调用DeleteGlobalRef
手动释放
作用:可以跨越多个线程,在程序员手动释放之前,一直有效。
jstring global_str;//设置global_strJNIEXPORT void JNICALL Java_com_tz_jni_TestNative_createGlobalRef(JNIEnv * env, jobject j_obj){ jstring obj = (*env)->NewStringUTF(env, "jni development is powerful!"); global_str = (*env)->NewGlobalRef(env, obj);}//访问global_strJNIEXPORT jstring JNICALL Java_com_tz_jni_TestNative_getGlobalRef(JNIEnv * env, jobject obj){ return global_str;}//释放global_strJNIEXPORT void JNICALL Java_com_tz_jni_TestNative_deleteGlobalRef(JNIEnv * env, jobject obj){ (*env)->DeleteGlobalRef(env, global_str);}复制代码
弱全局引用
调用NewWeakGlobalRef基于局部引用或全局引用创建,不会阻止GC回收所引用的对象,可以跨方法、跨线程使用。
节省内存,在内存不足时可以是释放所引用的对象 可以引用一个不常用的对象,如果为NULL,临时创建。
创建:NewWeakGlobalRef 销毁:DeleteGlobalWeakRef