在NDK中jmethodID需要释放吗?我看了一下资料,说jclass和jbyteArray及jstring都需要用DeleteLocalRef来释放,DeleteLocalRef的参数是jobject,但jmethodID的基类不是jobject,那它需要释放吗?

解决方案 »

  1.   

    关键是用什么函数释放,用DeleteLocalRef释放不了
      

  2.   

    有人在网上说GetMethodID返回的也是Local Reference,也需要用DeleteLocalRef释放,但是用这个编译报错!
      

  3.   

    http://dev.10086.cn/cmdn/bbs/thread-55111-1-1.html1、什么需要释放? 
    什么需要什么呢 ? JNI 基本数据类型是不需要释放的 , 如 jint , jlong , jchar 等等 。 我们需要释放是引用数据类型,当然也包括数组家族。如:jstring ,jobject ,jobjectArray,jintArray 等等。 当然,大家可能经常忽略掉的是 jclass ,jmethodID , 这些也是需要释放的哦 
      

  4.   

    DeleteLocalRef 一般不需要手动调用,shared_ptr<T> 对象(jni的引用,_jobject _jmethodid是其具体实现)出作用域,就会析构,同时--refcount.除非你这个函数会执行很久。NewGlobalRef 是在堆上创建shared_ptr<T> 对象。所以必须手动释放。以上T可以是基本类型,也可以是对象。释放不释放跟数据类型没关系,跟sp<>是栈对象还是堆对象有关。另外如下:
    (jmethodID)env->NewGlobalRef(env->GetMethodID(h264StreamCls, "getSPSNalu", "()[B"));
    是编译不过的,jmethodid 非jobject。
    但也并不是说jmethodid就不能全局引用。
    把env->GetMethodID(h264StreamCls, "getSPSNalu", "()[B"); 返回的jmethodid直接复制给一个全局的jmethodid变量,是可以出函数全局是使用的。
    这样做的原理是创建一个全局shared_ptr<T> 对象,引用T。弊端就是这将无法释放。不知道JNI设计人员出于何种考虑,这算是jni的一个bug,在android的platform下的jni是有NewGlobalRef(jmethodid)这个重载的。
      

  5.   

    补充上面,给遇到同样问题的人一些思路: * ReferenceTable overflow (max=512)
     Last 10 entries in JNI local reference table:
       502: 0x4055a668 cls=[B (29428 bytes)
       503: 0x4055a668 cls=[B (29428 bytes)
       504: 0x4055a668 cls=[B (29428 bytes)
       505: 0x4055a668 cls=[B (29428 bytes)
       506: 0x4055a668 cls=[B (29428 bytes)
       507: 0x4055a668 cls=[B (29428 bytes)
       508: 0x4055a668 cls=[B (29428 bytes)
       509: 0x4055a668 cls=[B (29428 bytes)
       510: 0x4055a668 cls=[B (29428 bytes)
       511: 0x4055a668 cls=[B (29428 bytes)
     JNI local reference table summary (512 entries):
          1 of Ljava/lang/Class; 188B
          1 of Ljava/lang/Class; 236B
          1 of Lcom/lisa/lm/jni/LisaMedia; 212B
          1 of Lcom/lisa/lm/media/record/H264Stream; 132B //以上4个是全局引用,stop时释放。      1 of [B 28B
          1 of [B 36B
         15 of [B 20020B (1 unique)
          1 of [B 23052B
        490 of [B 29428B (1 unique) 
      Memory held directly by tracked refs is 73332 bytes如果是C里调用java,返回数组。
    jbyteArray array = (jbyteArray)env->CallObjectMethod(h264StreamObj, getPPSNaluMid);
    即使jbyteArray array是在函数内部,是局部变量,也需要手动删除local引用。翻文档总结如下:
    对于FindClass 返回的一定需要调用DeleteLocalRef,还有jbyteArray 类型的变量需要DeleteLocalRef。
    NewString/ NewStringUTF/NewObject/ GetObjectField生成的需要DeleteLocalRef。
    以上返回的类型变量是malloc出来的,不是栈变量。出作用域不会被释放,需要手动。设计的真是令人发指!如下写法是不对的:
    SetObjectField(dwi, jfID, env->NewStringUTF(szDateTime))