Android开发实践:Java层与Jni层的数组传递
转载:http://www.linuxidc.com/Linux/2014-03/97561.htm
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的管理工作均由操作系统来负责。
Android开发实践:Java层与Jni层的数组传递的更多相关文章
- Java层与Jni层的数组传递(转)
源:Java层与Jni层的数组传递 Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的S ...
- Android 开发实践 ViewGroup 实现左右滑出窗口(二)
接上一篇 <Android 开发实践 ViewGroup 实现左右滑出窗口(一)http://www.cnblogs.com/inkheart0124/p/3532862.html> 源码 ...
- Android 开发实践 ViewGroup 实现左右滑出窗口(一)
利用假期把以前做的东西总结整理一下,先从简单的开始吧.实现的效果是这样的: 做了个截屏动画,比例有点不对了,凑合着看吧. 整个窗口有3部分组成,中间的主界面是个列表,左边的滑出界面是个菜单,右边的 ...
- Xamarin.Android开发实践(四)
原文:Xamarin.Android开发实践(四) Xamarin.Android下获取与解析JSON 一.新建项目 1.新建一个Android项目,并命名为为NetJsonList 2.右击引用,选 ...
- Xamarin.Android开发实践(五)
原文:Xamarin.Android开发实践(五) 一.服务的生命周期 服务与活动一样,在它的整个生命周期中存在着一些事件,下图可以很好解释整个过程以及涉及到的方法: 在真实的使用中,Service来 ...
- Xamarin.Android开发实践(三)
原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...
- Xamarin.Android开发实践(二)
原文:Xamarin.Android开发实践(二) 一.准备 开始学习本教程前必须先完成该教程http://www.cnblogs.com/yaozhenfa/p/xamarin_android_qu ...
- Xamarin.Android开发实践(一)
原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...
- Android开发中java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}
Android开发中java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: java.lang.NullPoi ...
随机推荐
- [转]busybox登陆后没要求输入密码的解决办法
转自:http://blog.chinaunix.net/uid-8058395-id-65785.html 1.制作好ramdisk之后 通过串口进入系统 却发现系统直接登录进去了 并没有要求用ro ...
- Audio Unit 介绍
关于 Audio Unit iOS 提供了音频处理插件,支持混音,声音均衡,格式转化,以及用于录音,回放,离线渲染,实时对话的输入输出.可以动态载入和使用这些强大而灵活的插件,在 iOS 应用中这些插 ...
- 适配器模式 & 装饰器模式
一.适配器模式:简单来讲,就是为了方便使用,完成从 一个接口 到 另一个接口 的 转换,这个负责转换的就是 适配器例如:Reader ——> InputStreamReader 通过类内部组合 ...
- 装多个版本jdk后,eclipse无法正常启动
需要在eclipse.ini中plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar后面指定jdk的路径. 指定jdk所在路径 -v ...
- BZOJ1179_APIO2009_抢掠计划_C++
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1179 一道用 Tarjan 缩点+SPFA 最长路的题(Tarjan 算法:http://ww ...
- ios 改变图片大小缩放方法
http://www.cnblogs.com/zhangdadi/archive/2012/11/17/2774919.html http://bbs.csdn.net/topics/39089858 ...
- 无法解析的外部符号 "public: static void __cdecl std::_String_base::_Xran(void)" (?_Xran@_String_base@std@@SAXXZ)"
采用下面的方法.重新编译了一下依赖的库,OK了. 问题描述: 今天用VS2010编译一个在VS2008下Coding的工程的时候,VS给出了一堆链接错误信息,如下图所示: 在ErrorList里面 ...
- UVA 1589:Xiangqi (模拟 Grade D)
题目: 象棋,黑棋只有将,红棋有帅车马炮.问是否死将. 思路: 对方将四个方向走一步,看看会不会被吃. 代码: 很难看……WA了很多发,还越界等等. #include <cstdio> # ...
- 漂亮的弹窗口插件——sweetAlert的使用
想必你已经受够了单调的alert弹窗吧? 为了更好的用户体验性,现在介绍一款漂亮的弹窗口插件——sweetAlert,现在就来介绍它的使用 1.首先在官网下载它的CSS和JavaScript文件:ht ...
- PHP将两个二维数组合并为一个二维数组的方法
$a = array(0 => Array(id => 66,class_name => math),1 => Array(id => 67,class_name =&g ...