美文网首页
JNI传值问题

JNI传值问题

作者: 明日即是今朝 | 来源:发表于2020-08-06 09:20 被阅读0次

    疑问点

    哪种传值的方式会好一点,涉及到的引用是否有内存问题

    简介

    使用NDK一般都需要java和c/c++的相互传值,java的值传递给c或者c的值传递给java,java传递给c比较简单,就直接放在参数里就行;c传递给java一般的方式有三种。

    • 通过反射调用java的方法传值
    • 通过c/c++ return
    • 通过参数传递过去,然后让c/c++修改内存

    实践

    我们来具体看一下这三种方式的使用方式:

    1.通过反射调用java的方法传值

       jclass clazz = env->GetObjectClass(jobject);
       onPrepareId = env->GetMethodID(clazz, "onPrepare", "()V");
       //调用方法传递值
       env->CallVoidMethod(instance, onPrepareId);
    

    这是反射传值,比较简单,也容易释放内存,在调用完方法后就可以释放到相关内存。但是这种在多个方法嵌套使用的时候就不太友好了,比如我还需要在onPrepare中再调用c/c++的代码,然后返回值需要接收,又要一个在java层写个方法去接手返回值,这样回调方法会有好几个比较乱和难管理。

    2.通过c/c++ return

    比如我们项目中现在需要把byte[]数组经过native音频重采样然后把值返回给java

    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;
    }
    

    那这里拿到值也没问题,但是JNI中NewByteArray 涉及到的内存,就没法回收了,这样会造成内存问题吗?我在android studio做了测试,监测了profiler的memory 状态,这样return传值是不会造成native的内存一直上涨。后来我又把return 去掉直接 测试NewByteArray会不会造成内存问题,发现也不会。这个时候我就猜测NewByteArray并不会造成内存泄漏,跟是否返回没有关系。后来找到了这篇文章,关于JVM的局部引用和全局引用的问题。
    https://wiki.jikexueyuan.com/project/jni-ndk-developer-guide/recommend.html
    NewByteArray是属于局部变量,走完这个c++的函数,就会被JVM自动释放掉,所以不会有内存问题。但是局部变量需不需要手动删除呢?不删除有没有影响?这个我将在下一篇中跟大家一起探讨。

    3.通过修改java传过去的参数

    上面的代码改成这个样子

    Java_xxxxx_PcmResample_resample(JNIEnv *env, jclass clazz, jbyteArray pcm,jbyteArray result) {
    //buff 是处理的指针数据
            jbyte* buff;
    //这样直接赋值给result 这个参数 就不用new也不用返回值了,java直接拿到result用就可以。这里可以实现吗?
            env->SetByteArrayRegion(result, 0, in.size, buff);
    }
    

    实践得出 在java取出 byte[] result 是可以拿到他的值的。可以看出这种传值的方式既没有内存问题,又不会存在第一种问题的嵌套问题。就所以这种方式应该是最好的传值方式。当然对于一些错误处理的回调函数,还是用第一种方式比较好,单独的一个方法处理错误返回。

    总结

    c++往java传值有三种方法
    1.反射传值主要用在错误回调里面,比较集中的场景
    2.直接return的方式在某些情况下不建议使用,详细可以见下一篇文章
    3.第三种修改java传过来的参数应该是最好的方案
    水平有限,如有错误,请谅解,也请不吝赐教。

    相关文章

      网友评论

          本文标题:JNI传值问题

          本文链接:https://www.haomeiwen.com/subject/vkabrktx.html