JNI 函数(五)数组操作

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。

  下面说明了特定的基本类型数组元素的具体函数:

  1. Get<PrimitiveType>ArrayElements 替换为表中某个实际的基本> 类型的函数
  2. 将 ArrayType 替换为对应的数组类型
  3. 将 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 种情况:

  1. 0:复制内容并释放 elems 缓冲区
  2. JNI_COMMIT:复制内容但不释放 elems 缓冲区
  3. JNI_ABORT:释放缓冲区而不复制可能的更改

  大多数情况下,程序员将 “0” 作为参数传递,因为这样可以确保固定和复制数组的一致行为。其他选项可以让程序员更好的控制内存。

  下面说明了特定的基本类型数组元素的具体函数:

  1. Release <PrimitiveType> ArrayElements 替换下面中某个实际的基本> 类型的函数
  2. 将 ArrayType 替换为对应的基本数组类型
  3. 将 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

  下面说明了特定的基本类型数组元素的具体函数:

  1. 将 Get<PrimitiveType> ArrayRegion 替换下面中某个实际的基本> 类型的函数
  2. 将 ArrayType 替换为对应的基本数组类型
  3. 将 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);

  主要是冲缓冲区复制基本类型的数组的函数

  下面说明了特定的基本类型数组元素的具体函数:

  1. Set<PrimitiveType>ArrayRegion 替换下面中某个实际的基本> 类型的函数
  2. 将 ArrayType 替换为对应的基本数组类型
  3. 将 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。

原文地址:https://www.cnblogs.com/Reverse-xiaoyu/p/14134563.html