在Java中数组分为两种:

1.基本类型数组

2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用)

一个能通用于两种不同类型数组的函数:

GetArrayLength(jarray array);

首先来看一下怎么处理基本类型的数组:

(1) Get<Type>ArrayElements(<Type>Array arr , jboolean* isCopide);

这类函数可以把Java基本类型的数组转换到C/C++中的数组,有两种处理方式,一种是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传回到本地代码中,处理完本地化的数组后,通过Release<Type>ArrayElements来释放数组

(2) Release<Type>ArrayElements(<Type>Array arr , <Type>* array , jint mode)

用这个函数可以选择将如何处理Java跟C++的数组,是提交,还是撤销等,内存释放还是不释放等

mode可以取下面的值:

0 :对Java的数组进行更新并释放C/C++的数组

JNI_COMMIT :对Java的数组进行更新但是不释放C/C++的数组

JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组

(3) GetPrimittiveArrayCritical(jarray arr , jboolean* isCopied);

(4) ReleasePrimitiveArrayCritical(jarray arr , void* array , jint mode);

也是JDK1.2出来的,为了增加直接传回指向Java数组的指针而加入的函数,同样的也会有同GetStringCritical的死锁的问题

(5) Get<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , <Type>* buffer);

在C/C++预先开辟一段内存,然后把Java基本类型的数组拷贝到这段内存中,这个方法和之前拷贝字符串的GetStringRegion方法的原理是类似的

(6) Set<Type>ArrayRegion(<Type>Array arr , jsize start , jsize len , const <Type>* buffer);

把Java基本类型的数组中的指定范围的元素用C/C++的数组中的元素来赋值

(7) <Type>Array New<Type>Array(jsize sz)

指定一个长度然后返回相应的Java基本类型的数组

在来看一下怎么处理对象型数组

JNI没有提供直接把Java的对象类型数组(Object[])直接转到C++中的Object[]数组的函数,而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[]数组进行操作由于去的对象数组没有进行拷贝,所以不需要释放任何资源

NewObjectArray可以通过指定长度跟初始值来创建某个类的数组

下面来看一下例子:操作两种类型的数组

Java中的代码:

[java] view
plain
copy

  1. package com.jni.demo;
  2. public class JNIDemo {
  3. //定义一个int型数组
  4. int[] arrays = {4,3,12,56,1,23,45,67};
  5. //定义Father对象数组
  6. Father[] objArrays = {new Father(),new Father(),new Father()};
  7. //定义一个本地方法
  8. public native void callCppFunction();
  9. public static void main(String[] args)throws Exception{
  10. //调用动态链接库
  11. System.loadLibrary("JNIDemo");
  12. JNIDemo jniDemo = new JNIDemo();
  13. jniDemo.callCppFunction();
  14. }
  15. }
  16. </span>

C++中的代码:

  1. #include<iostream>
  2. #include"com_jni_demo_JNIDemo.h"
  3. #include<algorithm>
  4. using namespace std;
  5. JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_callCppFunction (JNIEnv * env, jobject obj)
  6. {
  7. //获取Java中数组属性arrays的id
  8. jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");
  9. //获取Java中数组属性arrays的对象
  10. jintArray jint_arr = (jintArray)env->GetObjectField(obj,fid_arrays);
  11. //获取arrays对象的指针
  12. jint* int_arr = env->GetIntArrayElements(jint_arr,NULL);
  13. //获取数组的长度
  14. jsize len = env->GetArrayLength(jint_arr);
  15. //打印数组中的值
  16. cout<<"数组的值为:";
  17. for(int s =0;s<len;s++){
  18. cout<<int_arr[s]<<',';
  19. }
  20. cout<<endl;
  21. //新建一个jintArray对象
  22. jintArray jint_arr_temp = env->NewIntArray(len);
  23. //获取jint_arr_temp对象的指针
  24. jint* int_arr_temp = env->GetIntArrayElements(jint_arr_temp,NULL);
  25. //计数
  26. jint count = 0;
  27. //偶数位存入到int_arr_temp内存中
  28. for(jsize j=0;j<len;j++){
  29. if(j%2==0){
  30. int_arr_temp[count++] = int_arr[j];
  31. }
  32. }
  33. //打印int_arr_temp内存中的数组
  34. cout<<"数组中位置是偶数的值为:";
  35. for(jsize k=0;k<count;k++){
  36. cout<<int_arr_temp[k]<<',';
  37. }
  38. cout<<endl;
  39. //将数组中一段(0-2)数据拷贝到内存中,并且打印出来
  40. jint* buffer = new jint[len];
  41. //获取数组中从0开始长度为3的一段数据值
  42. env->GetIntArrayRegion(jint_arr,0,3,buffer);
  43. cout<<"打印数组中0-3一段值:";
  44. for(int l=0;l<3;l++){
  45. cout<<buffer[l]<<',';
  46. }
  47. cout<<endl;
  48. //将数组中的一段(3-7)设置成一定的值,并且打印出来
  49. jint* buffers = new jint[4];
  50. for(int n=0;n<4;n++){
  51. buffers[n] = n+1;
  52. }
  53. //将buffers这个数组中值设置到数组从3开始长度是4的值中
  54. env->SetIntArrayRegion(jint_arr,3,4,buffers);
  55. //从新获取数组指针
  56. int_arr = env->GetIntArrayElements(jint_arr,NULL);
  57. cout<<"数组中3-7这段的值变成了:";
  58. for(int m=0;m<len;m++){
  59. cout<<int_arr[m]<<',';
  60. }
  61. cout<<endl;
  62. //调用C++标准库中的排序方法sort(...),传递一个数组的开始指针和结束指针
  63. std::sort(int_arr,int_arr+len);
  64. //迭代打印数组中的元素
  65. cout<<"数组排序后的结果:";
  66. for(jsize i=0;i<len;i++){
  67. cout<<int_arr[i]<<',';
  68. }
  69. cout<<endl;
  70. //释放数组指针
  71. env->ReleaseIntArrayElements(jint_arr,int_arr,JNI_ABORT);
  72. //获取Java中对象Father数组属性的id
  73. jfieldID fid_obj_arrays = env->GetFieldID(env->GetObjectClass(obj),"objArrays","[Lcom/jni/demo/Father;");
  74. //获取Java中对象数组Father属性objArrays的对象
  75. jobjectArray jobj_arr = (jobjectArray)env->GetObjectField(obj,fid_obj_arrays);
  76. //从对象数组中获取索引值为1的对象Father
  77. jobject jobj = env->GetObjectArrayElement(jobj_arr,1);
  78. //获取Father对象的class对象
  79. jclass clazz_father = env->GetObjectClass(jobj);
  80. //获取Father对象中的function方法的id
  81. jmethodID id_father_function = env->GetMethodID(clazz_father,"function","()V");
  82. //调用Father对象中的function方法
  83. env->CallVoidMethod(jobj,id_father_function);
  84. //在本地创建一个大小为10的对象数组,对象的初始化都是jobj,也就是方法的第三个参数
  85. jobjectArray jobj_arr_temp = env->NewObjectArray(10,env->GetObjectClass(jobj),jobj);
  86. //获取本地对象数组中第4个对象
  87. jobject jobj_temp = env->GetObjectArrayElement(jobj_arr_temp,3);
  88. //调用Father对象中的function方法
  89. env->CallVoidMethod(jobj_temp,id_father_function);
  90. }
  91. </span>

在Eclipse编译运行结果如下:

不要以为这就结束了,后面还有很多内容呀!

Java中JNI的使用详解第五篇:C/C++中操作Java中的数组的更多相关文章

  1. Java中JNI的使用详解第三篇:JNIEnv类型中方法的使用

    转自: http://blog.csdn.net/jiangwei0910410003/article/details/17466369 上一篇说道JNIEnv中的方法的用法,这一篇我们就来通过例子来 ...

  2. Java中JNI的使用详解第四篇:C/C++中创建Java对象和String字符串对象及对字符串的操作方法

    首先来看一下C/C++中怎么创建Java对象:在JNIEnv中有两种方法是用来创建Java对象的: 第一种方法: jobject  NewObject(jclass clazz  , jmethodI ...

  3. Java中JNI的使用详解第六篇:C/C++中的引用类型和Id的缓存

    首先来看一下C/C++中的引用 从Java虚拟机创建的对象传到本地C/C++代码时会产生引用,根据Java的垃圾回收机制,只要有引用存在就不会触发该引用指向的Java对象的垃圾回收 第一.局部引用: ...

  4. Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

    上一篇说的是一个简单的应用,说明JNI是怎么工作的,这一篇主要来说一下,那个本地方法sayHello的参数的说明,以及其中方法的使用 首先来看一下C++中的sayHello方法的实现: JNIEXPO ...

  5. Java中JNI的使用详解第一篇:HelloWorld

    转自: http://blog.csdn.net/jiangwei0910410003/article/details/17465085 今天开始研究JNI技术,首先还是老套路,输出一个HelloWo ...

  6. Orchard详解--第五篇 CacheManager

    上一篇文章介绍了Orchard中的缓存,本篇主要针对CacheManager进行分析,CacheManager在Orchard中用于存储应用程序的配置信息以及框架内部的一些功能支持,包括整个拓展及拓展 ...

  7. JScript中的条件注释详解(转载自网络)

    JScript中的条件注释详解-转载 这篇文章主要介绍了JScript中的条件注释详解,本文讲解了@cc_on.@if.@set.@_win32.@_win16.@_mac等条件注释语句及可用于条件编 ...

  8. Objective-C中 Self和 Super详解

    Objective-C中 Self和 Super详解 Objective-C 中Self 和 Super 详解本文要介绍的内容,在 Objective-C 中的类实现中经常看到这两个关键字 self  ...

  9. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

随机推荐

  1. 获取请求url中的参数

    一.根据request获取参数 假设请求地址是: http://127.0.0.1:8020/books/?title=语文 那么后台的路由配置: re_path('books/$', views.B ...

  2. Django 自定义扩展命令

    import datetime import logger from django.conf import settings from django.db.models import Q from d ...

  3. vue 学习六 在组件上使用v-model

    其实这个部分应该是属于component,为什么把这玩意单独拿出来呢,原因是它这个东西比较涉及到了vue的事件,以及v-model指令的使用,还是比较综合的.所以就拿出来啦 父组件 <templ ...

  4. RAM SSO功能重磅发布 —— 满足客户使用企业本地账号登录阿里云

    阿里云RAM (Resource Access Management)为客户提供身份与访问控制管理服务.使用RAM,可以轻松创建并管理您的用户(比如雇员.企业开发的应用程序),并控制用户对云资源的访问 ...

  5. 重新开始学习C++

    从2002年,大二的那个夏天开始,就接触了C++这门语言,大学那会就是在老师不停教育下,背诵C++的各种特征,完全不知道C++干嘛用的,当然自然也是不知道汇编语言,C语言是干嘛用的,老师让学就学吧.那 ...

  6. Android编程:解决异常“android.view.InflateException: Binary XML file line # : Error inflating class”

    今天写程序发现一个问题,就是XML中报出android.view.InflateException异常,可能的原因有: 1.XML中使用到得组件名称是否书写正确(包名+类名),可以使用crtl+鼠标点 ...

  7. 二维差分前缀和——cf1202D(好题)

    直接枚举每个点作为左上角是可以做的,但是写起来较麻烦 有一种较为简单的做法是对一列或一行统计贡献 比如某一行的B存在的区间是L,R那么就有三种情况 1.没有这样的区间,即一行都是W,此时这行对答案的贡 ...

  8. Block 使用总结

    - (void)testBlockWeakObj1 { UILabel *tl = [[UILabelalloc]init];//本地局部变量 __weak UILabel *weakTL = tl; ...

  9. STM32嵌入式开发学习笔记(四):使用滴答计时器实现精准计时

    前面我们讲过,因为在STM32上没有系统时间的接口,因此无法调用sleep函数,在本文中,笔者将利用滴答计时器实现精准延时. 查阅技术手册,滴答计时器依赖于一个SysTick_Type类型寄存器,定义 ...

  10. SPOJ MAXMATCH - Maximum Self-Matching (FFT)

    题目链接:MAXMATCH - Maximum Self-Matching Description You're given a string s consisting of letters 'a', ...