博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android NDK 开发(四)JNI 中局部引用、全局引用和弱全局引用
阅读量:7119 次
发布时间:2019-06-28

本文共 2792 字,大约阅读时间需要 9 分钟。

hot3.png

前言

做过Java的朋友都知道,内存管理这一块是完全透明的,new一个类的实例时,只知道创建完这个类的实例后,会返回这个实例的一个引用,然后拿着这个引用去访问它的成员了(属性、方法),完全不用管JVM内部怎么实现的,如何为新建的对象申请内存,使用完之后如何释放内存,只需要知道有个垃圾回收器在处理这些事情就行了,然而,从Java虚拟机创建的对象传到C/C++代码时会产生引用,根据Java的垃圾回收机制,只要有引用存在就不回触发该引用所指向Java对象的垃圾回收;这些引用在JNI 中分为3种:全局引用(Global Reference)、局部引用 (Local Reference)、弱全局引用 (Week Global Reference) since JDK1.2。


原文链接请标明:

本文出自:【的博客】

正文

三种引用的区别

1、全局引用

全局引用可以跨方法、跨线程使用,直到被开发者显式释放。类似局部引用,一个全局引用在被释放前保证引用对象不被GC回收。和局部引用不同的是,没有那么多函数能够创建全局引用。能创建全局引用的函数只有 NewGlobalRef。以下例子说明了如何使用一个全局引用。

java native方法:

public native void createGlobalRef();    public native String getGlobalRef();    public native void deleteGlobalRef();

jni实现:

//全局引用//共享(可以跨多个线程),手动控制内存使用jstring global_str;//创建JNIEXPORT void JNICALL Java_com_study_jni_JniTest_createGlobalRef(JNIEnv *env, jobject jobj){
jstring obj = (*env)->NewStringUTF(env, "jni development is powerful!"); global_str = (*env)->NewGlobalRef(env, obj);}//获得JNIEXPORT jstring JNICALL Java_com_study_jni_JniTest_getGlobalRef(JNIEnv *env, jobject jobj){
return global_str;}//释放JNIEXPORT void JNICALL Java_com_study_jni_JniTest_deleteGlobalRef(JNIEnv *env, jobject jobj){
(*env)->DeleteGlobalRef(env, global_str);}

2、局部引用

一个局部引用仅在创建它的native函数及该函数调用的函数中有效。在一个native函数执行期间创建的所有局部引用将在该函数返回时被释放,创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性。

//模拟:循环创建数组JNIEXPORT void JNICALL Java_com_study_jni_JniTest_localRef(JNIEnv *env, jobject jobj){    int i = 0;    for (; i < 5; i++){        //创建Date对象        jclass cls = (*env)->FindClass(env, "java/util/Date");        jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "
", "()V"); jobject obj = (*env)->NewObject(env, cls, constructor_mid); //此处省略一百行代码... //不在使用jobject对象了 //通知垃圾回收器回收这些对象 //释放局部引用 (*env)->DeleteLocalRef(env, obj); //此处省略一百行代码... }}

上面代码中,省略了和我们无关紧要的代码,通过FindClass返回一个对java.util.Date对象的局部引用。


3、弱全局引用

节省内存,在内存不足时可以是释放所引用的对象,可以引用一个不常用的对象,如果为NULL,临时创建,弱全局引用使用NewGlobalWeakRef创建,使用DeleteGlobalWeakRef释放。下面简称弱引用。与全局引用类似,弱引用可以跨方法、线程使用。但与全局引用很重要不同的一点是,弱引用不会阻止GC回收它引用的对象,所以在使用时需要多加小心,它所引用的对象可能是不存在的或者已经被回收。

1.创建弱全局引用

用NewWeakGlobalRef函数对弱全局引用进行初始化,例如:

jclass weakGlobalclsweakGlobalcls = (*env)->NewWeakGlobalRef(env,localclazz);
2.引用的比较

给定两个引用(不管是全局、局部还是弱全局引用),我们只需要调用IsSameObject来判断它们两个是否指向相同的对象。例如:(*env)->IsSameObject(env, obj1, obj2)

如果obj1和obj2指向相同的对象,则返回JNI_TRUE(或者1),否则返回JNI_FALSE(或者0)。有一个特殊的引用需要注意:NULL,JNI中的NULL引用指向JVM中的null对象。如果obj是一个局部或全局引用,使用(*env)->IsSameObject(env, obj, NULL) 或者 obj == NULL 来判断obj是否指向一个null对象即可。但需要注意的是,IsSameObject用于弱全局引用与NULL比较时,返回值的意义是不同于局部引用和全局引用的。比如:

if(JNI_FALSE == (*env)->IsSameObject(env,weakGlobalcls,NULL)){//TODO 对象未被回收,可以使用}else{//TODO 对象被垃圾回收器回收,不能使用}

以上就是学习这jni 的三种引用的简单使用,相关的知识并没有深入详细的说明!O(∩_∩)O~~

转载于:https://my.oschina.net/xuhaozi/blog/780411

你可能感兴趣的文章
JSON文件中非法字符的处理
查看>>
c++异常处理
查看>>
CGI的一些知识点
查看>>
SQL Server误区30日谈-Day14-清除日志后会将相关的LSN填零初始化
查看>>
冒泡排序
查看>>
Java中的final
查看>>
简明Linux命令行笔记:touch
查看>>
Top 命令使用
查看>>
如何在多台机器上共享IOS证书
查看>>
最近遇到的一个问题,求解释
查看>>
IOS 开发,调用打电话,发短信,打开网址
查看>>
word实现转换成图片的实现
查看>>
人生如梦
查看>>
预装Win8系统的电脑安装Win7的方法(EFI安装Win7)
查看>>
Vim按键映射
查看>>
员工辞职是为了炒老板鱿鱼
查看>>
远程管理WinRM,Enter-PSSession
查看>>
2013第12周五小结
查看>>
32位与64位原子操作的问题
查看>>
jquery 引用
查看>>