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交流。

jni java返回数组_Android开发实践:Java层与Jni层的数组传递相关推荐

  1. java android 数组_Android开发基础之Java 数组

    Java 数组 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java 语言中提供的数组是用来存储固定大小的同类型元素. 你可以声明一个数组变量,如 n ...

  2. android java 调用栈_Android开发中打印方法调用栈

    概要 在日常开发和debug的过程中,我们都需要看看某一个方法的调用StackTrace,如果是crash或者异常被抛出的情况下会直接看到对应的StackTrace,如: 39 5939 E Andr ...

  3. java界面设计 代码_Android开发——纯JAVA代码方式界面设计

    之前我们写Android页面都是在XML文件里写的,今天我们换个口味,在JAVA文件里写我们的Android页面.至于为什么要用java来写,不直接在XML文件里写,这个问题的答案很简单,因为麻烦嘛, ...

  4. 安卓打开java文件管理器_Android开发之简单文件管理器实现方法

    本文实例讲述了Android开发之简单文件管理器实现方法.分享给大家供大家参考,具体如下: 这里运用Java I/O.ListActivity.Dialog.Bitmap等实现简单文件管理器,可以查看 ...

  5. android开发是java语言吗_android开发是用java语言吗?

    android开发的主流语言是java语言,但也可以使用其他语言,例可以通过Android NDK使用C/C++作为编程语言来开发应用程序,也可使用SL4A来使用其他各种脚本语言进行编程. Andro ...

  6. java安卓字体_Android开发之字体设置

    一.前言: 1.默认字体 Android SDK自带了四种字体:"normal""monospace","sans", "seri ...

  7. java输出体重指数_Android开发–身高体重指数(BIM)计算–完成BMI程序 | 学步园...

    /* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved. * 文件名称:修改表达用户界 ...

  8. java定焦点_Android 开发 Camera1_如何使用对焦功能

    前言 Camera1的自动对焦还是有一些坑值得开一个篇幅来讲解,一般对焦Mode有以下几种: Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO 连续自动对焦视 ...

  9. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

最新文章

  1. AI时代的中层支柱:统计学
  2. ant 改变表格数据_学不会这几个操作,面试时千万别说自己精通数据分析
  3. [YTU]_1046 ( 输入10个数字,然后逆序输出)
  4. pythongps聚类_Python中的GPS轨迹聚类
  5. 语义分割的时候,发的牢骚
  6. 另一个绑定事件的方式 为元素绑定事件的区别
  7. Linux awk 命令
  8. 唤醒控件曾经拥有的能力
  9. C# 使用int.TryParse,Convert.ToInt32,(int)将浮点类型转换整数时的区别
  10. aes算法实现c语言_以C语言实现归并排序为例,谈谈五大常用算法之一的“分治法”...
  11. 数据结构之二叉树:折纸问题——11
  12. UVA983 Localized Summing for Blurring【前缀和+最大子段和+DP】
  13. codeforces#237_div2_B Marathon
  14. jqgrid 单元格绑定点击事件_VBA代码解决方案第115讲:点击鼠标实现精准控制触发事件的VBA代码第二方案...
  15. mysql 15位升18位_身份证号码15位升18位规则
  16. ucla计算机科学博士排名,加州大学洛杉矶分校专业排名一览及最强专业推荐(QS世界大学排名)...
  17. Python三维绘图——Matplotlib
  18. linux启动项加命令,启动项 命令(linux 添加开机启动项的三种方法)
  19. 2.1 新版个人所得税计算
  20. 一款二次元风格好看的视频jiexi官网

热门文章

  1. php javascript对象,JavaScript 对象
  2. C++ cout格式化输出
  3. python的三个特性_Python3.9的7个特性
  4. 澄海哪里学机器人编程_少年学机器人编程
  5. C++重载流插入运算符与流提取运算符
  6. 坯子库曲面推拉教程_一招曲面流动,搞定99%异形建模
  7. 基础功能2-python修改文件中所有文件名
  8. 用cmd编译c++程序
  9. opencv resize
  10. 软件测试管理工具禅道开源版下载安装