jni java返回数组_Android开发实践: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的定义:

2b0aa3351e6ebe4e55983d7c22c6432c.png

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

c1c075a0124a7260f8baa579980a787c.png

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

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

首先看Native.java的定义:

d8f307b094f4e5df60c5f808a9aae52b.png

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

fe72d80a5aa7817b5c030c238f070e8a.png

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

三、 Direct Buffer 方式传递

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

首先看Native.java的定义:

c2c7297a5bec128c9b0ef52ca47971d3.png

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

290a947aabfc65297e71542d8d512b33.png

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

四、 总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

查出数字字符字段中非数字字符的记录

最近,将原来的数字符字段转换为数字时,总报错误:无效数字。 如何找出其中哪些是非数字字符的记录?比较麻烦的事。下面是用Oracle DB自带的函数translate可以找出来的 1.创建测试表 Create Table TestChar( ITEM_NUMBER VARCHAR…

jsp mysql 注入_由Jsp+Mysql注入到root权限的全程展 【好久没有安全类文章了,转一篇看看】...

由JspMysql注入到root权限的全程展最近有点空闲,所以写点垃圾文章来消磨一下时间.文中没有什么技术含量,如果要转载,请注明作者并保持文章的完整.很多人可能都知道asp,php的编程要防止sql注入漏洞,而并不知道jsp编程同样也需要防备sql注入漏洞.其实,一旦jsp代码有注入漏洞,将直…

MySQL Replication Error 处理一例

故障现象 MySQL slave status详情 mysql> show slave status\G *************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 10.10.10.101Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_L…

java中的time_java中的Time处理

得到当前时间1. Calendar.getInstance().getTime();2. new Timestamp(System.currentTimeMillis());3. new Timestamp((Calendar.getInstance().getTime()).getTime());--------------------------------|date------------------------------------------------------Simple…

ubuntu14.04LTS openssh-server 手动安装配置步骤

先用能上网的机器下载:zlib-1.2.5.tar.bz2、openssh-5.6p1.tar.gz、openssl-0.9.8o.tar.tar,接下来,准备安装。 步骤如下: 1、首先解压安装zlib:tar -xf zlib-1.2.5.tar.bz2,会在当前目录下生成zlib目录。进…

java tls 证书_在使用Java 8重新协商TLS_1.2期间,服务器证书更改受到限制

我对SSL很陌生,并且被看似已知的问题所困扰.我的应用程序是SSL客户端,并调用另一个为双向SSL启用的组件.两个组件中的证书都是正确的,有时连接工作正常.每个服务器都有自己的服务器证书和私钥,但具有相同的根证书和中间证书.服务器中的SSL检查在Apache SW LB中完成.|----------…

将前台json对象传入java后台

前台json格式的数据如何传入后台 1. 将要传入后台的数据组装成JSON格式的字符串: var jsonStr [{name:jim , age:20} , {name:king , age:26},{name:jge , age:30}] 2. 使用JQuery的ajax请求后台 jQuery.ajax({ type: "post", url: url, dataType : json, data : {m…

java windows wrapper_Java Service Wrapper 发布windows后台程序的方法

Java ServiceWrapper发布可执行jar文件的方法通过摸索,终于将我的程序转换成windows后台服务程序了,实现股票成交明细数据自动定时下载,很爽!现将心得要点记录如下:2.建立项目文件夹。例如 d:/myApp3.在该文件夹下建立…

Divide and conquer:Dropping tests(POJ 2976)

最大化平均值 题目大意:给定你n个分数,从中找出k个数,使∑a/∑b的最大值 这一题同样的也可以用二分法来做(用DP会超时,可见二分法是多么的实用呵!),大体上是这样子:假设最…

java中标准封装结构_java中的构造,封装

今天给大家讲一下面向对象中的构造,封装;构造:构造方法有以下几个特点:1.方法名和类名一致。2.无返回类型。接下来的几种构造样式,直接上代码吧://这是一个宠物类 有一个属性:名字(name)public …

设计模式 - 依赖倒置原则

先看文章一:http://www.cnblogs.com/painsOnline/p/5138806.html (前半部分) 在看文章二:http://baike.baidu.com/link?urlBPC2OUFFHc7l14iLo70URxt8ae4-Wukbl3S077cCYpZljhFOHeK5prDuuMCyU7kwJwYvFnN1nKdevzsTrbJY7_ &#xff0…

《白日梦想家》观后感

To see the world, things dangerous to come to, To see behind walls, to draw closer, To find each other and to feel That is the Purpose of LIFE.” 这部片子我很喜欢,大概我在现实生活中,也就是一个梦想家吧。想过很多事,但是真正去…

Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle...

Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq index2 3. 检查约束 (Check Counstraint) 对该列数据的范围、格式的限制(如:年龄、性别等)2 4. 默认约束 (Default Couns…

linux隐藏tomcat版本_Ubuntu 14.04隐藏Tomcat-7.0.52的版本号与操作系统类型

一般情况下,软件的漏洞信息和特定版本,特定操作系统是相关的,因此,软件的版本号以及操作系统类型对攻击者来说是很有价值的。在默认情况下,Tomcat会在返回信息中把自身的版本号,操作系统类型都显示出来&…

将java.util.Date类型转换成json时,使用JsonValueProcessor将date转换成希望的类型

将java.util.Date类型转换成json时,使用JsonValueProcessor将date转换成希望的类型 问题描述: java里面时间类型转换成json数据就成这样了:"createTime":{"date":30,"day":3,"hours":15,"minut…

java redis 商品秒杀_使用redis秒杀出现产品超发现象求解?

亲测,用ab 压测并发500 请求4000 无超卖!header("content-type:text/html;charsetutf-8");$redis new redis();$result $redis->connect(127.0.0.1, 7379);$redis->watch("mywatchlist");$len $redis->hlen("mywat…

删除日志为0的文件

find . -size 0 -name "*.log" -exec rm {} \; 转载于:https://www.cnblogs.com/getong/p/5143366.html

在java中8421_JAVA常量介绍

常量:在程序执行过程中,其值不发生改变的量;1、分类: 字面值常量和自定义常量;1、字面值常量有以下几种:字符串常量、小数常量、整数常量、字符常量、布尔常量(true、false)、空常量(null);2、整数常量…

自定义tabbar

/** * 注意:* 打开自定义tabbar的背景视图的交互* 选中的tabb视图高度为tabbar背景视图的高度/2-选中视图高度/2* 选中视图加载到tabbar背景视图上* label注意居中,imgView注意选择适应模式,都加载到tabbar背景视图* 设置点击手势的点击事件…

java候选码计算的替换法_候选码求解方法

候选码的求解基本方法集合一、求解候选码基本算法的具体步骤.第1 步,求关系模式R 的最小函数依赖集F第2 步, 按照上面的定义, 分别计算出UL ,UR , UB (UL 表示仅在函数依赖集中各依赖关系式左边出现的属性的集合; UR 表示仅在函数依赖集中各依赖关系式右边出现的属性的集合;另…