JNI中几种引用的区别

2019-12-19  本文已影响0人  董成鹏

我们知道JNI提供了一些实例和数组类型做为不透明的引用供本地代码使用,比如jobject,jarray,jstring等。

JNI中的引用其实分为三种类型:全局引用,局部引用,弱引用。

全局引用和局部引用的区别在于生命周期,当方法返回的时候,局部引用会被自动释放,但是全部引用和弱引用必须手动释放。

局部引用和全局引用会阻止GC,但是弱引用不会。

下面详细讲一下三种引用的区别:

局部引用
局部引用指向的VM内部空间会在本地方法返回的之后被销毁。我们不能尝试通过static来保存一个局部引用。在上一节MyNewString中,通过NewObject方法创建的引用就是局部引用,但是它被返回给Java继续使用了。

局部引用在方法返回时自动销毁,也可以通过DeleteLocalRef在不使用的时候直接销毁。这样会更及时的GC。

我们在方法中通过JNIEnv创建的引用,绝大部分都是局部引用。

全局引用
全局引用可以跨方法和线程进行访问,必须手动释放。
全局引用只能有一个方法创建,那就是NewGlobalRef方法。下面这个版本的MyNewString展示了怎么使用一个全局引用。

jstring MyNewString(JNIEnv *env, jchar chars, jint len){
  static jclass strClass = NULL;
  ...
  if(strClass == NULL){
    jclass localClass = (*env)->FindClass(env,"java/lang/String");
    strClass = (*env)->NewGlobalRef(env, localClass);

    ...
    //局部引用已经不需要了
    (*env)->DeleteLocalRef(env.localClass);
    if(strClass == null){
      return NULL;
    }
  }
}

全局引用释放的时候只能通过DeleteGlobalRef来释放

弱引用
弱引用不会影响GC,只能通过NewGlobalWeakRef创建,使用DeleteGlobalRef来释放。

弱引用可以跨线程和跨方法使用。我们一般也是通过static关键字来保存弱引用。

三种引用的比较

对于任何一种引用,包括全局引用,局部引用,弱引用,我们都可以通过IsSameObject来判断两个引用是否指向同一个JVM对象(*env)->IsSameObject(env,obj1,obj2).

在JNI中 NULL指向了Java中的null。对于全局和局部引用,(*env)->IsSameObject(env,obj,NULL)和obj==NULL是一样的。

但是在弱引用中含义会有一点变化,当obj是弱引用的时候,(*env)->IsSameObject(env,obj,NULL);代表的是该弱引用所指向的空间是否被回收。

上一篇 下一篇

猜你喜欢

热点阅读