NDK学习笔记-JNI的引用

JNI中的引用意在告知虚拟机何时回收一个JNI变量

JNI引用变量分为局部引用和全局引用

局部引用

局部引用,通过DeletLocalRef手动释放对象

原因

  • 访问一个很大的Java对象,使用之后还用进行复杂的耗时操作
  • 创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性

局部引用示例

Java中存在native方法

public native void localRef();

在native中有调用对象,但对象在使用以后就不再使用,此时就可以将对象释放掉,以节约内存
此处举一个循环创建数组的,数组中建立对象的例子

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_localRef
(JNIEnv *env, jobject jobj)
{
	int i = 0;
	for (;i < 10; i++)
	{
		//创建Date对象
		jclass cls = (*env)->FindClass(env, "java/util/Date");
		jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
		jobject obj = (*env)->NewObject(env, cls, constructor_mid);

		//使用完毕,通知垃圾回收器回收对象
		(*env)->DeleteLocalRef(env, obj);
		printf("已通知垃圾回收器回收对象
");
	}
}

全局引用

共享(可以跨多个线程),手动控制内存使用
此处通过创建一个字符串来说明,native中存在一个全局变量jstring global_str;

创建

Java

public native void createGlobalRef();

C

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_createGlobalRef
(JNIEnv *env, jobject jobj)
{
	jstring lobj = (*env)->NewStringUTF(env, "jni golbal test");
	global_str = (*env)->NewGlobalRef(env, lobj);
}

获取

Java

public native String getGlobalRef();

C

JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getGlobalRef
(JNIEnv *env, jobject jobj)
{
	return global_str;
}

释放

Java

public native void deleteGlobalRef();

C

JNIEXPORT void JNICALL Java_com_cj5785_jni_JniTest_deleteGlobalRef
(JNIEnv *env, jobject jobj)
{
	(*env)->DeleteGlobalRef(env, global_str);
}

弱全局引用

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

原文地址:https://www.cnblogs.com/cj5785/p/10664678.html