一.前言

  JNI中的数组类型分为基本类型数组和引用类型数组,他们的处理方式是不一样的。基本类型数组中的元素都是jni基本数据类型,可以直接访问;但是引用类型的数组中的元素是一个类的实例,不能直接访问,需要使用jni中的函数进行访问。

二.基本类型数组的交互

  1.java层声明的native函数如下:

public native double[] arrayAsArgs(int[] a);//求数组的和以及平均数,并以数组的形式返回

  2.native层代码:

jdoubleArray native_arrayAsArgs(JNIEnv *env,jobject thiz,jintArray array){
jint *a=env->GetIntArrayElements(array, nullptr);//获取java层数组的值,并赋给jint*指针变量
jsize length=env->GetArrayLength(array);//获取java层数组的长度
jint sum=0;
jdouble avg=0.0;
for(int i=0;i<length;i++){
sum+=*(a+i);//访问每一个数组元素并累加
}
avg=(jdouble)sum/length;
env->ReleaseIntArrayElements(array,a,0);//和GetIntArrayElements()是一对的,使用完之后就要释放内存,防止内存泄漏
jdouble result[]={(jdouble)sum,avg};
jdoubleArray result1=env->NewDoubleArray(2);//开辟内存空间,相当于new double[2]
env->SetDoubleArrayRegion(result1,0,2,result);//给数组赋值
return result1;
}

三.引用类型数组的交互

  1.java层声明的native函数如下:

public native String[] quoteArrayAsArgs(String[] s);//从java中传入引用数组到native层,并返回相同的引用数组到java层

  2.native层代码:

jobjectArray native_quoteArrayAsArgs(JNIEnv *env,jobject thiz,jobjectArray s){
jclass clazz=env->FindClass("java/lang/String");
jsize length=env->GetArrayLength(s);
jstring str;
jstring str1[length];
for(int i=0;i<length;i++){//获取java层引用数组中每个元素的值,并存储在str1数组中
str=(jstring)env->GetObjectArrayElement(s,i);
str1[i]=str;
}
jobjectArray str2;
str2=env->NewObjectArray(length,clazz, nullptr);//为引用数组开辟内存,相当于new String[length]
for(int i=0;i<length;i++){
env->SetObjectArrayElement(str2,i,str1[i]);
}
return str2;
}

四.二维数组的交互

  二维数组可以看作特殊的一维数组,数组中的每个元素的类型是一维数组,也就是说每个元素是一个引用类型的数据,这样理解之后,代码就好写了。

  1.java层声明的native函数如下:

public native char[][] twoDimenArrayAsArgs(char[][] c);//原封不动的返回c

  2.native层代码:

jobjectArray native_towDimenArrayAsArgs(JNIEnv *env,jobject thiz,jobjectArray c){
jsize rows=env->GetArrayLength(c);//获取行数
jcharArray cc=(jcharArray)env->GetObjectArrayElement(c,0);
jsize cols=env->GetArrayLength(cc);//获取列数
jchar result[rows][cols];
for(int i=0;i<rows;i++){
cc=(jcharArray)env->GetObjectArrayElement(c,i);
jchar *character=env->GetCharArrayElements(cc, nullptr);
for(int j=0;j<cols;j++){
result[i][j]=*(character+j);
}
env->ReleaseCharArrayElements(cc,character,0);
}
jclass clazz=env->FindClass("[C");//char[]的Class对象
jobjectArray ret=env->NewObjectArray(rows,clazz, nullptr);
for(int i=0;i<rows;i++){
jcharArray jcharArray=env->NewCharArray(cols);
env->SetCharArrayRegion(jcharArray,0,cols,result[i]);
env->SetObjectArrayElement(ret,i,jcharArray);
}
return ret;
}

  如果是其他类型的数组,将类型换成其他类型即可,代码不用变。

JNI编程之java层和native层的数组数据的交互的更多相关文章

  1. Android Java层,Native层,Lib层打印Log简介【转】

    本文转载自:https://blog.csdn.net/AndroidMage/article/details/52225068 说明: 这里我根据个人工作情况说明在各个层打印log.如有问题欢迎拍砖 ...

  2. framework层和native层实现联网控制(iptable方式)

    最近工作中,需要开发一个功能----联网控制,这个功能其实用过root的安卓机应该都知道,禁止某个应用连接移动网络或者wifi. root后,通过su去执行iptable的命令就可以根据uid去控制应 ...

  3. 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则

    前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...

  4. 并发编程之 Java 三把锁

    前言 今天我们继续学习并发.在之前我们学习了 JMM 的知识,知道了在并发编程中,为了保证线程的安全性,需要保证线程的原子性,可见性,有序性.其中,synchronized 高频出现,因为他既保证了原 ...

  5. 并发编程之Java内存模型

    在介绍Java内存模型之前,先来了解一下为什么要有内存模型,以及内存模型是什么.然后我们基于对内存模型的了解,学习Java内存模型以及并发编程的三大特性. 为什么要有内存模型 在计算机中,所有的运算操 ...

  6. 并发编程之Java锁

    一.重入锁 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized(重量级) 和 ReentrantLock(轻量级)等等 ) .这些已经写好提供的锁为我们开发提 ...

  7. Java并发编程之java.util.concurrent包下常见类的使用

    一,Condition 一个场景,两个线程数数,同时启动两个线程,线程A数1.2.3,然后线程B数4.5.6,最后线程A数7.8.9,程序结束,这涉及到线程之间的通信. public class Co ...

  8. spark 独立应用编程之 Java 编程

    文章更新于:2020-04-03 按照惯例,文件附上链接放在文首. 文件名:apache-maven-3.6.3-bin.tar.gz 文件大小:9.1 MB 下载链接:https://www.lan ...

  9. 白话说编程之java线程

    线程和进程: 在说多线程之前,我们先来研究一下线程,说到线程,我们又不得不说到进程,因为很多初学者会把线程和进程分不清,搞混淆. 进程: 是操作系统系统运行的最小单元.怎么理解这句话,可以这样去对比, ...

  10. 并发编程之java内存模型(Java Memory Model ,JMM)

    一.图例 0.两个概念 Heap(堆):运行时的数据区,由垃圾回收负责,运行时分配内存(所以慢),对象存放在堆上 如果两个线程,同时调用同一个变量,怎两个线程都拥有,该对象的私有拷贝 (可以看一下,T ...

随机推荐

  1. CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!) A-E

    比赛链接 A 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { i ...

  2. Go 匿名返回值的坑——这道题据说 90% 的同学都答错了!

    今天分享的内容比较基础,准确地说是 Go 的语言特性--命名.匿名返回值. 先看下面的例子,猜测会输出什么? package main func main() { println(A()) print ...

  3. MIT 6.5840 Raft Implementation(2B, Log Replication)

    Raft实现思路+细节(2B) 任务分解 2B中最主要的任务就是进行日志的复制.Raft是一个强领导人的系统,这意味着所有的日志添加都是由领导人发起的,与之相类似的,还有很多其他的结论(它们都是比较显 ...

  4. Truncate 和 Delete 的区别与选择

    1)事务和日志 delete   语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行回滚操作. truncate table  则 一次性地从表中删除所有 ...

  5. 自用 .net C# CSV文件写入读取工具类

    using System.Data; using System.IO; using System.Linq; using System.Text; using System.Text.RegularE ...

  6. CTF比赛中Web的php伪协议类型题小结

    php协议类型 file:// - 访问本地文件系统 http:// - 访问 HTTP(s) 网址 ftp:// - 访问 FTP(s) URLs php:// - 访问各个输入/输出流(I/O s ...

  7. npm install 下载依赖的过程

    首先检查.npmrc文件,项目级.npmrc文件>用户级的.npmrc文件>全局性的.npmrc文件>npm内置的.npmrc文件 是否有lock文件 没有lock文件 从npm远程 ...

  8. GIT保存记录原理之commit对象

    GIT 中提交对象非常的重要,我们通过它记录代码提交过程.进行文件保存.回退等操作,那么它是怎样帮助我们记录这些信息的呢?其实就是都保存在项目根目录的 .git 文件夹中. 新建空项目 ```gitD ...

  9. 清理MySQL的binlog日志

    前言 MySQL的binlog是以二进制形式打印的日志,没设置自动删除的话,时间长了就会占用大量存储空间.删除MySQL的binlog日志有两种方法:自动删除和手动删除. 自动删除 永久生效:修改My ...

  10. 给你的 SpringBoot 工程部署的 jar 包瘦瘦身吧!

    之前有写过一篇有关maven插件的文章:spring-boot-maven-plugin插件详解 一.需求背景 我们知道Spring Boot项目,是可以通过java -jar 包名 启动的. 那为什 ...