Java中JNI的使用详解第五篇:C/C++中操作Java中的数组(一)

2014-11-24 07:25:48 · 作者: · 浏览: 0

Java中数组分为两种:

1.基本类型数组

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

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

GetArrayLength(jarray array);


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

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

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


(2) Release ArrayElements( Array arr , * 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 ArrayRegion( Array arr , jsize start , jsize len , * buffer);

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


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

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


(7) Array New Array(jsize sz)

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


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

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

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


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

Java中的代码:

[java] view plaincopy 在CODE上查看代码片 派生到我的代码片
  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. C++中的代码:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #include
    2. #include"com_jni_demo_JNIDemo.h"
    3. #include
    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 cout< }
    18. cout<
    19. //新建一个jintArray对象
    20. jintArray jint_arr_temp = env->NewIntArray(len);
    21. //获取jint_arr_temp对象的指针
    22. jint* int_arr_temp = env->GetIntArrayElements(jint_arr_temp,NULL);
    23. //计数
    24. jint count = 0;
    25. //偶数位存入到int_arr_temp内存中
    26. for(jsize j=0;j if(j%2==0){
    27. int_arr_temp[count++] = int_arr[j];
    28. }
    29. }
    30. //打印int_arr_temp内存中的数组
    31. cout<<"数组中位置是偶数的值为:";
    32. for(jsize k=0;k cout< }
    33. cout<
    34. //将数组中一段(0-2)数据拷贝到内存中,并且打印出来
    35. jint* buffer = new jint[len];
    36. //获取数组中从0开始长度为3的一段数据值
    37. env->GetIntArrayRegion(jint_arr,0,3,buffer);
    38. cout<<"打印数组中0-3一段值:";
    39. for(int l=0;l<3;l++){
    40. cout< }
    41. cout<
    42. //将数组中的一段(3-7)设置成一定的值,并且打印出来
    43. jint* buffers = new jint[4];
    44. for(int n=0;n<4;n++){
    45. buffers[n] = n+1;
    46. }
    47. //将buffers这个数组中值设置到数组从3开始长度是4的值中
    48. env->SetIntArrayRegion(jint_arr,3,4,buffers);
    49. //从新获取数组指针
    50. int_arr = env->GetIntArrayElements(jint_arr,NULL);
    51. cout<<"数组中3-7这段的值变成了:";
    52. for(int m=0;m cout< }
    53. cout<
    54. //调用C++标准库中的排序方法sort(...),传递一个数组的开始指针和结束指针
    55. std::sort(int_arr,int_arr+len);
    56. //迭代打印数组中的元素