JNI——訪問數組

JNI在處理基本類型數組和對象數組上面是不一樣的。對象數組裏面是一些指向對象實例或者其它數組的引用。 html

由於速度的緣由,先經過GetXXXArrayElements函數把簡單類型的數組轉化成本地類型的數組,並返回其數組的指針,而後經過該指針來對拷貝數組進行處理。
對拷貝數組處理完後,經過ReleaseXXXArrayElements函數把修改後的拷貝數組的反射到java數組,

而後釋放全部相關的資源。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緩衝區來訪問這些元素。spa

 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(棧)上被很快地分配,並且複製少許數組元素的代價是很小的。這對函數的另一個優勢就是,容許你經過傳入一個索引和長度來實現對子字符串的操做。code

若是你沒有一個預先分配的 C 緩衝區,而且原始數組長度未定,而本地代碼又不想在獲取數組元素的指針時阻塞的話,使用 Get/ReleasePrimitiveArrayCritical 函數對。就像Get/ReleaseStringCritical函數對同樣,這對函數很當心地使用,以免死鎖。htm

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 }    
相關文章
相關標籤/搜索