美文网首页
Android开发实践:Java层与Jni层的数组传递

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

作者: marine0131 | 来源:发表于2016-11-15 10:44 被阅读0次

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/1360240

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的定义:

Paste_Image.png

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

Paste_Image.png

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


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

首先看Native.java的定义:

Paste_Image.png

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

Paste_Image.png

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

三、 Direct Buffer 方式传递


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

首先看Native.java的定义:

Paste_Image.png

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

Paste_Image.png

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

四、 总结


关于Java与Jni层的数组传递就介绍到这里了,其实并不复杂,希望上述代码对初学者能有所帮助,有任何疑问或者不清楚的地方欢迎留言或者来信lujun.hust@gmail.com交流,或者关注我的新浪微博 @卢_俊 获取最新的文章和资讯。

相关文章

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

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http:...

  • 春招笔记(十四)

    1.是否熟悉Android jni开发,jni如何调用java层代码 在Android开发中,使用NDK开发的需求...

  • JNI开发之传递自定义对象

    一、前言 Android进行JNI开发时,有可能需要传递自定义的Java对象,这里包括从Java层传到Natvie...

  • JNI创建变量和释放变量

    jni中的数据传递就两种:c层传到java层;java层传到c层。 1 当数据从java传递到c 1.1 传递基本...

  • Android游戏开发实践(1)之NDK与JNI开发02

    Android游戏开发实践(1)之NDK与JNI开发02 承接上篇Android游戏开发实践(1)之NDK与JNI...

  • JNI 原理

    我们都知道JNI结构是 Java 层 -> JNI -> Native 层, 以此实现Java 层和Native层...

  • Android JNI学习

    JNI是Android中比较重要的一块知识,Java层与C/C++层进行调用的桥梁。所以今天就来学习一下JNI相关...

  • Android JNI 开发

    一、JNI 与 Android JNI 是 Java 提供的用于在跨平台系统中,与系统本地代码进行交互的一层应用程...

  • Android JNI之加载第三方so库

    JNI全称是Java Native Interface,为Java本地接口,是连接Java层与Native层的桥梁...

  • 1. java的数据类型的签名

    开发jni经常需要在jni层调用java层的方法,或者创建引用,这个时候就需要用到java的属性或者方法的签名,详...

网友评论

      本文标题:Android开发实践:Java层与Jni层的数组传递

      本文链接:https://www.haomeiwen.com/subject/nzbkpttx.html