源:Java层与Jni层的数组传递

Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni层也需要把从Socket接收到的数据流返回给Java层。我简单地总结了一下,从Java层到Jni层,从Jni层到JAVA层,各有3种传递方式,下面用代码示例简单地介绍一下。

示例代码的主要文件有两个,一个是Native.java,是Java层的类;另一个是Native.c,是JNI层的文件,关键的地方我都用注释添加到代码中了,完整的代码见博文后面的附件。

一、 从Java传递数组到Jni层

Jni层接收到Java层传递过来的byte[]数组,一般有2个函数来获取它的值,一个 GetByteArrayRegion,另一个是 GetByteArrayElements ,前者是进行值拷贝,将Java端数组的数据拷贝到本地的数组中,后者是指针的形式,将本地的数组指针直接指向Java端的数组地址,其实本质上是JVM在堆上分配的这个数组对象上增加一个引用计数,保证垃圾回收的时候不要释放,从而交给本地的指针使用,使用完毕后指针一定要记得通过ReleaseByteArrayElements进行释放,否则会产生内存泄露。

首先看Native.java的定义:

再看看对应的native.c的实现代码:

二、 从Jni层传递数组到Java层

把Jni层定义的数组传递到Java层,一般有两种方法,一种是通过native函数的返回值来传递,另一种是通过jni层回调java层的函数来传递,后者多用于jni的线程中。无论哪种方法,都离不开 SetByteArrayRegion 函数,该函数将本地的数组数据拷贝到了 Java 端的数组中。下面只介绍前一种方式,即通过native函数返回值的方式传递jni层的数组,回调的方式其实用法类似,就不详细介绍了。

首先看Native.java的定义:

再看看native.c是如何实现的:

由上述代码示例可以看出,首先通过 NewByteArray 在堆上分配数组对象,然后通过SetByteArrayRegion 把本地的数组数据拷贝到堆上分配的数组中去,然后通过返回值将分配的数组对象返回到Java层即可。对于回调的方式,这几步操作也是一样的,唯一的不同是,回调方式不是以返回值的方式将数组对象返回给Java层,而是在回调函数中,以回调函数参数的形式返回给Java层。

三、 Direct Buffer 方式传递

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

首先看Native.java的定义:

再看看native.c是如何实现的:

由上述代码可以看出,其中使用起来还是很简单的,Jni层只需要通过GetDirectBufferAddress函数即可获取到这块共享的内存的地址,Direct Buffer的管理工作均由操作系统来负责。

四、 总结

关于Java与Jni层的数组传递就介绍到这里了,其实并不复杂,希望上述代码对初学者能有所帮助,有任何疑问或者不清楚的地方欢迎留言或者来信lujun.hust@gmail.com交流。

转载于:https://www.cnblogs.com/LittleTiger/p/4557066.html

Java层与Jni层的数组传递(转)相关推荐

  1. java层 android_Android开发实践:Java层与Jni层的数组传递

    Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni ...

  2. jni java返回数组_Android开发实践:Java层与Jni层的数组传递

    Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni ...

  3. Android开发实践:Java层与Jni层的数组传递

    Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni ...

  4. saf java_Android SAF实现外置SD卡的写入(JAVA层与JNI层hook)

    1. 前言 之前折腾了了一下MINE模拟器,发现SDL全是在JNI层fopen操作的,而安卓的SAF则是JAVA层通过DocumentFile和docUri来实现写入的.一种方法是通过去的File D ...

  5. saf java_Android SAF实现外置SD卡的写入JAVA层与JNI层hook

    JAVA层SAF核心代码 通过DocumentFile来实现写入,Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)发送请求docUri,然后onActivityResu ...

  6. saf java_[原创]Android Storage Access Framework(SAF)框架实现外置SD卡的写入(JAVA层与JNI层HOOK)...

    1. 前言 之前折腾了了一下MINE模拟器,发现SDL全是在JNI层fopen操作的,而安卓的SAF则是JAVA层通过DocumentFile和docUri来实现写入的.一种方法是通过去的File D ...

  7. Android 底层驱动开发步骤——linux内核层、HAL层、JNI层

    1.Linux驱动实现 2.Linux内核驱动测试 3.Android HAL层实现 4.Aidl实现 5.Service java实现 6.Service jni 实现 7.注册service和jn ...

  8. java web分层和层间数据传递 vo bo po (转载)

    还记得97年左右开始的胖客户机和瘦客户机之争吗?之后又是CS和BS之争,然后又是两层和多层之争...,十年之后的今天我们再回过头看这些争论,一切似乎看起来都那么理所应当:程序怎么能不分层啊?可是再想一 ...

  9. java web分层和层间数据传递 vo bo po

    还记得97年左右开始的胖客户机和瘦客户机之争吗?之后又是CS和BS之争,然后又是两层和多层之争...,十年之后的今天我们再回过头看这些争论,一切似乎看起来都那么理所应当:程序怎么能不分层啊?可是再想一 ...

最新文章

  1. python之路_Python之路【第二篇】:Python基础(一)
  2. 【Android 逆向】代码调试器开发 ( ptrace 函数 | 读寄存器 | 写寄存器 )
  3. Github上删除仓库、项目方法演示
  4. MySQL的查询性能优化——《深究MySQL》
  5. 4.1.2 私有成员与公有成员
  6. c#多维数组的建立及操作 总结
  7. 我的世界手机版服务器显示即将推出,我的世界手机版领域服即将开启 什么是领域服...
  8. 人工智能之基于face_recognition的人脸检测与识别
  9. 线程队列-queue
  10. 把旧系统迁移到.Net Core 2.0 日记(1) - Startup.cs 解析
  11. c++远征之多态篇——运行时类型识别(RTTI)
  12. 【Python】range和xrange区别
  13. RocketMQ怎么保证队列顺序消费
  14. SSh三大框架的作用
  15. mysql数据库升幂_斯特林数
  16. win10安装nessus8.10
  17. 小白的python学习之路-turtle画不同大小的五角星
  18. Window7开机速度有点慢的解决办法
  19. 智能窗帘研究制作_智能窗帘的制作方法
  20. python实现和‘对象’qq自动续火

热门文章

  1. HDU 4628 Pieces(DP + 状态压缩)
  2. 深入浅出多线程系列之四:简单的同步 lock
  3. 数据结构之——队列与循环队列
  4. 基于大数据的用户行为预测
  5. 阿里云华北3超大规模数据中心开服 ECS全系列降价20%
  6. linux ---jenkins的安装与配置
  7. 技术网站 --入门无忧网
  8. objective-c如何在linux下进入Modern模式
  9. Vmware中安装RHEL5
  10. 【集训队互测2015】最大异或和