Android Java与JNI层互传数据总结

标签: androidJNI数据传递
1454人阅读 评论(0) 收藏 举报
分类:

在开发中常常会遇到从Java层传递数据到JNI层,然后在JNI拿到数据后就可以用C语言进行操作了,操作完数据后通常还需要把处理后的数据传回Java层。下面分别进行小结。

从Java层传到JNI层

  • 使用GetByteArrayRegion的方式
    该方法的本质是将Java端数组数据拷贝到本地的数组中,所以在JNI对数据修改后Java端的数据并没有改变。
  • 使用GetPrimitiveArrayCritical
    GetPrimitiveArrayCritical 表面上可以得到底层数据指针,在JNI层修改数组时Java层的数据也会变。But,如果只使用GetPrimitiveArrayCritical获取数据,程序运行一段时间内存会crash。所以,使用GetPrimitiveArrayCritical时必须使用ReleasePrimitiveArrayCritical ,通过测试发现当数据量大时执行ReleasePrimitiveArrayCritical会非常耗时。

从JNI层传到Java层

  • 把Jni层的数组传递到Java层,一般有两种方法,一种是通过native函数的返回值来传递,另一种是通过jni层回调java层的函数来传递,后者多用于jni的线程中或是数据量较大的情况。无论哪种方法,都离不开 SetByteArrayRegion 函数,该函数将本地的数组数据拷贝到了 Java 端的数组中。

注意上面的方式中都会涉及到内存拷贝,根据实战经验,在Android系统中,一旦数据量变大,拷贝一次内存将非常耗时。所以上述方式在追求效率时不推荐使用。解决的方法可以尝试让JAVA层和JNI共享内存的方式。最后找到了两种方式。


Java层和JNI层共享内存空间

  • 使用GetByteArrayElements方式
    该方式是指针的形式,将本地的数组指针直接指向Java端的数组地址,其实本质上是JVM在堆上分配的这个数组对象上增加一个引用计数,保证垃圾回收的时候不要释放,从而交给本地的指针使用,使用完毕后指针一定要记得通过ReleaseByteArrayElements进行释放,否则会产生内存泄露。

    unsigned char* psrcImg = (unsigned char*)(env->GetByteArrayElements(srcImg,0));  
    unsigned char* pBufferI420 = (unsigned char*) (env->GetByteArrayElements(dstImg,0));
    
    if (psrcImg == NULL || pBufferI420 == NULL)
    {
      return -1;
    }
    env->ReleaseByteArrayElements(srcImg,(jbyte*)psrcImg,0);
    env->ReleaseByteArrayElements(dstImg,(jbyte*)pBufferI420,0);

    注意if那里最好加上,网上查了说,get那里可能失败,失败得到的psrcImg是NULL,Release的时候程序就会崩。

  • Direct Buffer 方式传递。
    Java和Jni层的数组传递还有一个比较重要的方式,就是通过Direct Buffer来传递,这种方式类似于在堆上创建创建了一个Java和Jni层共享的整块内存区域,无论是Java层或者Jni层均可访问这块内存,并且Java端与Jni端同步变化,由于是采用的是共享内存的方式,因此相比于普通的数组传递,效率更高,但是由于构造/析构/维护这块共享内存的代价比较大,所以小数据量的数组建议还是采用上述方式,Direct Buffer方式更适合长期使用频繁访问的大块内存的共享。具体可使用GetDirectBufferAddress获得共享的内存地址。

综上,在图像算法开发中,我采用了GetByteArrayElements-ReleaseByteArrayElements的方式来传递图像数据。此外,在开发Android上的算法时,尽量避免内存拷贝,特别是JNI层。

Reference:
http://blog.csdn.net/xinchen200/article/details/25333047
http://zsaber.com/blog/p/107

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:153784次
    • 积分:2431
    • 等级:
    • 排名:第16731名
    • 原创:83篇
    • 转载:6篇
    • 译文:0篇
    • 评论:66条
    文章分类
    最新评论