转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119545225
本文出自【赵彦军的博客】
在 JNI 中,有三种引用类型
- 全局引用
- 局部引用
- 弱引用
局部引用
在方法中定义的局部引用,可以不用手动释放,在程序运行结束后,会自动释放。但是有一种情况,比如在方法中有 for 循环,如果产生大量的局部引用,会占用大量内存。所以一种比较好的编程习惯就是,产生的局部变量,一旦不再使用,就手动释放一下。
void DeleteLocalRef(jobject localRef)
举例说明:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
jstring str = env->NewStringUTF("string");
//释放局部变量
env->DeleteLocalRef(str);
}
全局引用
顾名思义,全局引用就是生命周期特别长,方法结束后不会自动释放内存。
创建全局变量:
jobject NewGlobalRef(jobject obj)
举个例子:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
static jclass strClass = nullptr;
if (strClass == nullptr) {
//创建局部变量
jclass cls = env->FindClass("java/lang/String");
//全局引用赋值
strClass = static_cast<jclass>(env->NewGlobalRef(cls));
//释放局部引用
env->DeleteLocalRef(cls);
} else {
//使用全局变量
}
}
需要注意的是 ,static 不能修饰局部变量,因为局部变量在程序退出的时候,会自动释放。那么 static 修饰的变量就变成了野指针。
释放全局引用
void DeleteGlobalRef(jobject globalRef)
举例说明:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
static jclass strClass = nullptr;
if (strClass == nullptr) {
//创建局部变量
jclass cls = env->FindClass("java/lang/String");
//全局引用赋值
strClass = static_cast<jclass>(env->NewGlobalRef(cls));
//释放局部引用
env->DeleteLocalRef(cls);
} else {
//使用全局变量
}
//释放全局引用
env->DeleteGlobalRef(strClass);
}
弱引用
弱引用的定义和java 弱引用的定义是一样的。
全局引用不会被 GC , 但是弱引用会在内存不足的情况下,被GC。所以在使用 弱引用之前要判断一下该引用是否被GC 。
判断方法:
jboolean IsSameObject(jobject ref1, jobject ref2)
举例说明:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
static jclass strClass = nullptr;
if (strClass == nullptr) {
//创建局部变量
jclass cls = env->FindClass("java/lang/String");
//弱引用赋值
strClass = static_cast<jclass>(env->NewWeakGlobalRef(cls));
//释放局部引用
env->DeleteLocalRef(cls);
} else {
}
//判断是否被GC
bool isGC = env->IsSameObject(strClass, nullptr);
if (isGC) {
//弱引用被回收了
} else {
//弱引用没有被回收
}
//释放全局引用
env->DeleteWeakGlobalRef(strClass);
}
总结
- 1、全局引用可以做缓存,对象复用。可以避免频繁的创建对象
- 2、弱引用会在内存不足的情况下被回收,所以弱引用在使用之前要判断是否为 Null
- 3、局部引用会在方法结束时自动释放,如果有循环频繁创建局部引用,会占用大量内存,需要手动释放