JNI 函數(五)數組操作
(一)、獲取數組的長度
函數原型:jsize GetArrayLength(JNIEnv *env, jarray array)
返回數組的長度
參數:
env:JNI 接口指針
array:Java 數組
返回:
數組的長度
(二)、創建對象數組
函數原型:jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);
創建一個新的對象數組,它的元素的類型是 elementClass,並且所有元素的默認值是 initialElement。
參數:
env:JNI 接口指針
length:數組大小
elementClass:數組元素類
initialElement:數組元素的初始值
返回:
Java 數組對象,如果無法構造數組,則返回 NULL
異常:
如果內存不足,則拋出 OutOfMemoryError
(三)、獲取數組元中的某個元素
函數原型:jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index);
返回元素中某個位置的元素
參數:
env:JNI 接口指針
array:Java 數組
index:數組下標
返回:
Java 對象
異常:
如果index下標不是一個有效的下標,則會拋出 ArrayIndexOutOfBoundsException
(四)、設置數組中某個元素的值
函數原型:void SetObjectArrayElement(JNIEnv *env,jobjectArray array,jsize index,jobject value);
設置下標為 index 元素的值。
參數:
env:JNI 接口指針
array:Java 數組
index:數組下標
value:數組元素的新值
異常:
如果 index 不是有效下標,則會拋出 ArrayIndexOutOfBoundsException
如果 value 不是元素類的子類,則會拋出 ArrayStoreException
(五)、創建基本類型數組系列
通用函數類型:ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
用於構造基本類型數組對象的一系列操作。下面說明了特定基本類型數組的創建函數。可以把 New<PrimitiveType>Array 替換為某個實際的基本類型數組創建函數 ,然后將 ArrayType 替換為相應的數組類型
New<PrimitiveType>Array Routines | Array Type |
NewBooleanArray() | jbooleanArray |
NewByteArray() | jbyteArray |
NewCharArray() | jcharArray |
NewShortArray() | jshortArray |
NewIntArray() | jintArray |
NewLongArray() | jlongArray |
NewFloatArray() | jfloatArray |
NewDoubleArray() | jdoubleArray |
參數:
env:JNI 接口指針
length:數組長度
返回:
Java 數組,如果無法創建該數組,則返回 NULL。
(六)、獲取基本類型數組的中數組指針系列
通用函數類型:NativeType * Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, jboolean * isCopy);
一組返回類型是基本類型的數組指針。在調用相應的 Release<PrimitiveType>ArrayElements() 函數前將一直有效。由於返回的數組可能是 Java 數組的副本,因此,對返回數組的變更沒有在基本類型中反應出來。除非了調用了一組返回基本類型數組體的函數。結果在調用相應的 Release<PrimitiveType>ArrayElements() 函數前將一直有效。由於返回的數組可能是 Java 數組的副本,因此對返回數組的更改不必在基本類型數組中反映出來,直到調用 “ Release<PrimitiveType>ArrayElements() ” 函數。
如果 isCopy 不是 NULL,*isCopy 在復制完成后即被設為 JNI_TRUE 。如果未復制,則設為 JNI_FALSE。
下面說明了特定的基本類型數組元素的具體函數:
- 將 Get<PrimitiveType>ArrayElements 替換為表中某個實際的基本> 類型的函數
- 將 ArrayType 替換為對應的數組類型
- 將 NativeType 替換為本地變量
不管布爾數組在 Java 虛擬機總如何表示,GetBooleanArrayElements() 將始終返回一個 jboolean 類型的指針,其中每一個字節代表一個元素(開包表示)。內存中將確保所有其他類型的數組為連續的。
Get<PrimitiveType>ArrayElements Routines | Array Type | Native Type |
GetBooleanArrayElements() | jbooleanArray | jboolean |
GetByteArrayElements() | jbyteArray | jbyte |
GetCharArrayElements() | jcharArray | jchar |
GetShortArrayElements() | jshortArray | jshort |
GetIntArrayElements() | jintArray | jint |
GetLongArrayElements() | jlongArray | jlong |
GetFloatArrayElements() | jfloatArray | jfloat |
GetDoubleArrayElements() | jdoubleArray | jdouble |
參數:
env:JNI 接口指針
array:Java 數組
isCopy:指向布爾值的指針
返回:
返回指向數組元素的指針,如果操作失敗,則返回 NULL
(七)、釋放基本類型的數組系列
通用函數原型:void Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode);
通知虛擬機 Native 不再訪問數組的元素了。elems 參數是使用相應的 Get <PrimitiveType> ArrayElements() 函數數組返回的指針。如果有需要的話,該函數復制復制所有的 elems 上的變換到原始數組元素上去。mode 參數提供了數組 buffer 應該怎么被釋放。如果elems 不是 array 的一個副本,mode 並沒有什么影響。
mode 的取值 有如下 3 種情況:
- 0:復制內容並釋放 elems 緩沖區
- JNI_COMMIT:復制內容但不釋放 elems 緩沖區
- JNI_ABORT:釋放緩沖區而不復制可能的更改
大多數情況下,程序員將 “0” 作為參數傳遞,因為這樣可以確保固定和復制數組的一致行為。其他選項可以讓程序員更好的控制內存。
下面說明了特定的基本類型數組元素的具體函數:
- 將 Release <PrimitiveType> ArrayElements 替換下面中某個實際的基本> 類型的函數
- 將 ArrayType 替換為對應的基本數組類型
- 將 NativeType 替換為本地變量
下面描述了基本類型數組釋放的詳情。 您應該進行以下替換:
Release<PrimitiveType>ArrayElements Routines | Array Type | Native Type |
ReleaseBooleanArrayElements() | jbooleanArray | jboolean |
ReleaseByteArrayElements() | jbyteArray | jbyte |
ReleaseCharArrayElements() | jcharArray | jchar |
ReleaseShortArrayElements() | jshortArray | jshort |
ReleaseIntArrayElements() | jintArray | jint |
ReleaseLongArrayElements() | jlongArray | jlong |
ReleaseFloatArrayElements() | jfloatArray | jfloat |
ReleaseDoubleArrayElements() | jdoubleArray | jdouble |
參數:
env:JNI 接口指針
array:Java 數組
elems:指向基本類型的數組的指針
mode:釋放模式
(8)、將基本類型數組某一區域復制到緩沖區中
函數原型:Get<PrimitiveType> ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);
復制基本類型的數組給 buff
下面說明了特定的基本類型數組元素的具體函數:
- 將 Get<PrimitiveType> ArrayRegion 替換下面中某個實際的基本> 類型的函數
- 將 ArrayType 替換為對應的基本數組類型
- 將 NativeType 替換為本地變量
Get<PrimitiveType>ArrayRegion Routine | Array Type | Native Type |
GetBooleanArrayRegion() | jbooleanArray | jboolean |
GetByteArrayRegion() | jbyteArray | jbyte |
GetCharArrayRegion() | jcharArray | jchar |
GetShortArrayRegion() | jshortArray | jshort |
GetIntArrayRegion() | jintArray | jint |
GetLongArrayRegion() | jlongArray | jlong |
GetFloatArrayRegion() | jfloatArray | jfloat |
GetDoubleArrayRegion() | jdoubleArray | jdouble |
參數:
env:JNI 接口指針
array:Java 數組
start:開始索引
len:需要復制的長度
buf:目標 buffer
異常:
如果索引無效,則拋出 ArrayIndexOutOfBoundsException
(九)、基本類型數組的某一區域從緩沖區中復制回來
函數原型:void Set<PrimitiveType> ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, const NativeType *buf);
主要是沖緩沖區復制基本類型的數組的函數
下面說明了特定的基本類型數組元素的具體函數:
- 將 Set<PrimitiveType>ArrayRegion 替換下面中某個實際的基本> 類型的函數
- 將 ArrayType 替換為對應的基本數組類型
- 將 NativeType 替換為本地變量
Set<PrimitiveType>ArrayRegion Routine | Array Type | Native Type |
SetBooleanArrayRegion() | jbooleanArray | jboolean |
SetByteArrayRegion() | jbyteArray | jbyte |
SetCharArrayRegion() | jcharArray | jchar |
SetShortArrayRegion() | jshortArray | jshort |
SetIntArrayRegion() | jintArray | jint |
SetLongArrayRegion() | jlongArray | jlong |
SetFloatArrayRegion() | jfloatArray | jfloat |
SetDoubleArrayRegion() | jdoubleArray | jdouble |
參數:
env:JNI 接口指針
array:Java 數組
start:開始索引
len:需要復制的長度
buf:源 buffer
異常:
如果索引無效則會拋出 ArrayIndexOutOfBoundsException
(十)、補充
從 JDK/JER 1.1 開始提供 Get/Release<primitivetype>ArrayElements 函數獲取指向原始數組元素的指針。如果 VM 支持鎖定,則返回指向原始數組的指針,否則,復制。
從 JDK/JRE 1.3 開始引入新的功能即便 VM 不支持鎖定,本地代碼也可以獲取數組元素的直接指針,
函數原型:void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
函數原型:void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);
雖然這兩個函數與上面的 Get/Release <primitivetype> ArrayElements 函數很像,但是在使用這個功能的時候,還是有很多的限制。
在調用 GetPrimitiveArrayCritical 之后,調用 ReleasePrimitiveArrayCritical 之前,這個區域是不能調用其他 JNI 函數,而且也不能調用任何可能導致線程阻塞並等待另一個 Java 線程的系統調用。
比如,當前線程不能調用 read 函數來讀取,正在被其他所寫入的 stream。