简介jni(五)

全剧引用/局部引用/弱全局引用

从Java虚拟机创建的对象传入到本地c/c++代码时会产生引用。根据Java的垃圾回收机制,只要有引用存在就不会出发该引用指向的Java对象的垃圾回收。

JNI引用分为:

全局引用(Global Reference)

局部引用(Local Reference)

弱全局引用(Weak Global Reference)


局部引用

最常见的引用类型,基本上通过JNI返回的引用都是局部引用。例如使用NewObject就会返回创建出来的示例的局部引用,局部引用只在该native函数中有效,所有在该函数中产生的局部引用,都会在函数返回的时候自动释放,也可以使用 DeleteLocalRef函数手动释放该引用。

在局部引用会函数返回时会自动释放还需要手动释放函数的:实际上局部引用存在,就会防止其指向的对象被垃圾回收,尤其是当一个局部引用指向一个很庞大的对象,或是一个循环中生成了局部引用,最好的做法就是在使用完该对象后,或是在该循环尾部把这个引用释放掉,以确保在垃圾回收器被触发的时候被回收。

在局部引用的有效期中,可以传递到别的本地函数中,要强调的是它的有效期仍然只是在一次的Java本地函数调用中,所以千万不能用c++全局变量保存它或是把它定义为c++静态局部变量。

全局引用

全局引用可以跨越当前线程,在多个native函数中有效,不过需要编程人员手动来释放该引用,全局引用存在期间会防止在Java的垃圾回收中回收。

与局部引用不同,全局引用的创建不是由JNI自动创建的,全局引用是需要调用NewGlobalRef函数,而释放需要调用ReleaseGlobalRef函数。

弱全局引用

Java 1.2新出来的功能,与全局引用相似,创建跟删除都需要编程人员来进行。这种引用与全局引用一样可以在多个本地代码中有效,也可跨越多线程有效。不一样的是,这种引用将不会阻止垃圾回收器回收这个引用所指向的对象。

使用NewWeakGlobalRef跟ReleaseWeakGlobalRef来产生和接触引用。

  jboolean IsSameObject(jobject obj1, jobject obj2) {
        return functions->IsSameObject(this,obj1,obj2);
    }
这个函数对于弱全局引用还有一个特别的功能。把NULL传入要比较的对象中,就能够判断弱全局引用所指向的Java对象是否被回收。


缓存jfieldID/jmethodID

取得jfieldID跟jmethodID的时候会通过该属性/方法名称加上签名来查询相应的jfieldID/jmethodID.这种查询相对来说开销较大,我们可以将这些fieldID/methodID缓存起来,这样在只需要查询一次,以后就使用缓存起来的ID就可以了。

两种缓存方式:

1.在用的时候缓存(caching at the point of Use)

2.在Java类初始化时缓存(caching at the Defining Class's Inititalizer)


在第一次使用的时候缓存

在native code中使用static局部变量来保存已经查询过的id,这样就不会在每次的函数调用时查询,而只要第一次查询成功后就保存起来了。

不过在这种情况下就不得不考虑多线程同时呼叫次函数时可能会导致同时查询的危机,不过这种情况是无害的,因为查询同一个属性或方法的id通常返回的是一样的值。

在Java类初始化的时候缓存

更好的一个方式就是在任何native函数调用前把id全部存起来,我们可以让java在第一次加载这个类的时候首先调用本地代码初始化所以的属性或方法的id,这样的话就可以省去多次的确认id是否存在的语句,当然这些id是定义在c/c++的全局。使用这样的还有好处,当Java类卸载或是重新加载的时候,也会重新呼叫,该本地代码来重新计算id。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值