zoukankan      html  css  js  c++  java
  • JNI——访问数组

    JNI在处理基本类型数组和对象数组上面是不同的。对象数组里面是一些指向对象实例或者其它数组的引用。 

    因为速度的原因,先通过GetXXXArrayElements函数把简单类型的数组转化成本地类型的数组,并返回其数组的指针,然后通过该指针来对拷贝数组进行处理。
    对拷贝数组处理完后,通过ReleaseXXXArrayElements函数把修改后的拷贝数组的反射到java数组,

    然后释放所有相关的资源。

    基本类型数组:

    获取数组元素指针的对应关系:
      函数            数组类型
      GetBooleanArrayElements   boolean
       GetByteArrayElements    byte
      GetCharArrayElements     char
      GetShortArrayElements    short
      GetIntArrayElements     int
       GetLongArrayElements    long
      GetFloatArrayElements     float
      GetDoubleArrayElements   double
      
    释放数组元素指针的对应关系:
      Function            Array Type
       ReleaseBooleanArrayElements   boolean
       ReleaseByteArrayElements    byte
       ReleaseCharArrayElements    char
       ReleaseShortArrayElements    short
       ReleaseIntArrayElements     int
       ReleaseLongArrayElements    long
       ReleaseFloatArrayElements    float
       ReleaseDoubleArrayElements   double

    数组的引用类型是一般是jarray或者jarray的子类型jintArray。就像jstring不是一个C字符串类型一样,jarray也不是一个C数组类型。
    所以,不要直接访问 jarray。你必须使用合适的JNI函数来访问基本数组元素:

    使用GetIntArrayRegion 函数来把一个 int数组中的所有元素复制到一个C缓冲区中,然后我们在本地代码中通过C缓冲区来访问这些元素。

     1 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) 
     2 { 
     3      jint buf[10]; 
     4      jint i, sum = 0; 
     5      (*env)->GetIntArrayRegion(env, arr, 0, 10, buf); 
     6      
     7     for (i = 0; i < 10; i++) { 
     8          sum += buf[i]; 
     9      } 
    10      return sum; 
    11 } 

    JNI支持一系列的Get/Release<Type>ArrayElement 函数,这些函数允许本地代码获取一个指向基本类型数组的元素的指针。

     1 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) 
     2  { 
     3      jint *carr; 
     4      jint i, sum = 0; 
     5      carr = (*env)->GetIntArrayElements(env, arr, NULL); //推荐使用
     6      if (carr == NULL) { 
     7          return 0; /* exception occurred */ 
     8      } 
     9      for (i=0; i<10; i++) { 
    10          sum += carr[i]; 
    11      } 
    12      (*env)->ReleaseIntArrayElements(env, arr, carr, 0); 
    13      return sum; 
    14  }

    如果你想在一个预先分配的C缓冲区和内存之间交换数据,应该使用Get/Set</Type>ArrayRegion系列函数。这些函数会进行越界检查,在需要的时候会有可能抛出ArrayIndexOutOfBoundsException异常。 
    对于少量的、固定大小的数组,Get/Set<Type>ArrayRegion是最好的选择,因为C缓冲区可以在Stack(栈)上被很快地分配,而且复制少量数组元素的代价是很小的。这对函数的另外一个优点就是,允许你通过传入一个索引和长度来实现对子字符串的操作。

    如果你没有一个预先分配的 C 缓冲区,并且原始数组长度未定,而本地代码又不想在获取数组元素的指针时阻塞的话,使用 Get/ReleasePrimitiveArrayCritical 函数对。就像Get/ReleaseStringCritical函数对一样,这对函数很小心地使用,以避免死锁。

    Get/Release<type>ArrayElements 系列函数永远是安全的。JVM 会选择性地返回一个指针,这个指针可能指向原始数据也可能指向原始数据复制。

    对象数组:
    JNI提供了一个函数对来访问对象数组。GetObjectArrayElement返回数组中指定位置的元素,而SetObjectArrayElement修改数组中指定位置的元素。
    与基本类型的数组不同的是,你不能一次得到所有的对象元素或者一次复制多个对象元素。
    字符串和数组都是引用类型,你要使用Get/SetObjectArrayElement来访问字符串数组或者数组的数组。

    下面的例子调用了一个本地方法来创建一个二维的 int数组,然后打印这个数组的内容:

     1 class ObjectArrayTest { 
     2      private static native int[][] initInt2DArray(int size); 
     3      public static void main(String[] args) { 
     4          int[][] i2arr = initInt2DArray(3); 
     5          for (int i = 0; i < 3; i++) { 
     6              for (int j = 0; j < 3; j++) { 
     7                   System.out.print(" " + i2arr[i][j]); 
     8              } 
     9              System.out.println(); 
    10          } 
    11      } 
    12      static { 
    13          System.loadLibrary("ObjectArrayTest"); 
    14      } 
    15  } 

    静态本地方法 initInt2DArray 创建了一个给定大小的二维数组。执行分配和初始化数组任务的本地方法可以是下面这样子的:

     1 JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass cls, int size) 
     2 { 
     3      jobjectArray result; 
     4      int i; 
     5      jclass intArrCls = (*env)->FindClass(env, "[I"); 
     6      if (intArrCls == NULL) { 
     7          return NULL; /* exception thrown */ 
     8      } 
     9      
    10      result = (*env)->NewObjectArray(env, size, intArrCls,  NULL); //分配第一维
    11      
    12      if (result == NULL) { 
    13          return NULL; /* out of memory error thrown */ 
    14      } 
    15      
    16      for (i = 0; i < size; i++) { 
    17          jint tmp[256];  /* make sure it is large enough! */ 
    18          int j; 
    19          jintArray iarr = (*env)->NewIntArray(env, size); //创建第二维数据
    20          if (iarr == NULL) { 
    21              return NULL; /* out of memory error thrown */ 
    22          } 
    23          for (j = 0; j < size; j++) { 
    24              tmp[j] = i + j; 
    25          } 
    26          (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); 
    27          (*env)->SetObjectArrayElement(env, result, i, iarr); 
    28          (*env)->DeleteLocalRef(env, iarr); 
    29      } 
    30      return result; 
    31  } 

    转自:http://www.cnblogs.com/lijunamneg/archive/2012/12/22/2828922.html

     1 Java_com_array_arrayTest_arrayUse( JNIEnv* env,jobject thiz,jobjectArray arrayData)      
     2 {   
     3    
     4       jint i,j;    
     5     
     6       int row = (*env)->GetArrayLength(env, arrayData);//获得行数      
     7   
     8       jarray myarray = ((*env)->GetObjectArrayElement(env, arrayData, 0));    
     9     
    10       int col =(*env)->GetArrayLength(env, myarray); //获得列数    
    11     
    12       jint jniData[row][col];         
    13     
    14       for (i = 0; i < row; i++){    
    15     
    16           myarray = ((*env)->GetObjectArrayElement(env, arrayData, i));    
    17     
    18           jint *coldata = (*env)->GetIntArrayElements(env, (jintArray)myarray, 0 );    
    19     
    20           for (j=0; j<col; j++) {    
    21               jniData [i] [j] = coldata[j]; //取出JAVA类中arrayData的数据,并赋值给JNI中的数组  
    22           }    
    23   
    24          (*env)->ReleaseIntArrayElements(env, (jintArray)myarray, coldata,0 );  
    25     
    26       }    
    27     
    28 }    
  • 相关阅读:
    RHEL7: How to configure a rc-local service
    安装 jemalloc for mysql
    aws rhel 7 安装GUI ,配置VNC
    官方推荐的MySQL参数设置值
    Linux HugePages及MySQL 大页配置
    Linux Transparent Huge Pages 对 Oracle 的影响
    Linux的Transparent Hugepage与关闭方法
    Linux HugePages 配置与 Oracle 性能关系说明
    How To Change Log Rate Limiting In Linux
    MySQL 8.0窗口函数
  • 原文地址:https://www.cnblogs.com/zl1991/p/6393650.html
Copyright © 2011-2022 走看看