JNI的引用问题

2020-08-06  本文已影响0人  明日即是今朝

问题

1.Java调用JNI的效率比Java调用java的效率要低很多(这个可以去测试对比下),而且JNI中的findClass()等方法比较耗时,不可能每次都去调用,怎么做缓存?
2.上次博客遗留的问题,C给java传值的时候,直接return了数据,NewByteArray也没有造成内存的泄漏,这里面涉及到了什么?

实践

释放内存和局部引用

我们先拿上次博客没说透的问题来看下。

Java_xxxxx_PcmResample_resample(JNIEnv *env, jclass clazz, jbyteArray pcm) {
        //xxxx省略处理pcm的过程
        //buff 是处理的指针数据
        jbyte* buff;
        jbyteArray data = env->NewByteArray(in.size);
        env->SetByteArrayRegion(data, 0, in.size, buff);
        return data;
}

这里我直接返回了data,NewByteArray并没有造成内存泄漏,这是为什么?这里其实有两层问题。

Java_xxxxx_PcmResample_resample(JNIEnv *env, jclass clazz, jbyteArray pcm) {
        //xxxx省略处理pcm的过程
        //buff 是处理的指针数据
      jbyte* buff;
      int i=0;
      while(i<1000000){
      jbyteArray data = env->NewByteArray(in.size);
        env->SetByteArrayRegion(data, 0, in.size, buff);
    }
      return data;
}

如果我们在while里面执行多次这个NewByteArray以后,我们就会发现程序崩溃了。崩溃的原因是因为local ref over flow 局部变量的表满了,每个进程对于局部变量都会维护一张表,局部变量的数量是有限的,如果超过了就崩溃,具体是多少我也没尝试,网上说是512。那这里因为程序迟迟不能出去,所以导致局部变量一直增加最终导致崩溃,所以这种情况下我们就需要手动的在循环里面调用DeleteLocalRef去释放内存了。

Java_xxxxx_PcmResample_resample(JNIEnv *env, jclass clazz, jbyteArray pcm) {
        //xxxx省略处理pcm的过程
        //buff 是处理的指针数据
      jbyte* buff;
      int i=0;
      while(i<1000000){
      jbyteArray data = env->NewByteArray(in.size);
      env->SetByteArrayRegion(data, 0, in.size, buff);
      env->DeleteLocalRef(pArray);
    }
      return data;
}

缓存JNI数据

对于基本数据类型我们把它放在类里面他就可以他直接可以跨方法跨线程使用,如果是jobject对象,例如jclass,为了防止每次都去读取耗费时间,我们需要把它缓存起来,这个时候就需要把它置为全局变量就可以,关于全局变量和弱全局变量,大家可以去看下这个博客,讲的很清楚,没有什么疑问点所以我就不重复了。
https://blog.csdn.net/xyang81/article/details/44657385

总结

弄明白jni的引用问题很关键,因为这涉及到你编码时候对于内存使用的正确性,也涉及到整个程序的内存问题。
水平有限,如有错误,请谅解,也请不吝赐教。

上一篇 下一篇

猜你喜欢

热点阅读