JNI完全指南(五)——字符串与数组

2016-11-15  本文已影响1885人  798fe2ac8685

标签(空格分隔): JNI完全指南

版本:1
作者:陈小默
声明:禁止商业,禁止转载

发布于:作业部落简书CSDN博客


上一篇:JNI完全指南(四)——对象操作


[toc]


五、字符串与数组

5.1 Java字符串

5.1.1 新建Java字符串

在JNI中,如果需要使用一个Java字符串,可以采用如下方式新建String对象。

jstring NewString(JNIEnv *env, const jchar *unicodeChars,
jsize len);

存在异常

5.1.2 获取Java字符串长度

通过以下方法我们能够获取到Java字符串的长度

jsize GetStringLength(JNIEnv *env, jstring string);

5.1.3 从Java字符串获取字符数组

我们可以通过以下方法从Java字符串获取字符数组,当使用完毕后,我们需要调用ReleaseStringChars进行释放。

const jchar * GetStringChars(JNIEnv *env, jstring string,
jboolean *isCopy);

5.1.4 释放从Java字符串中获取的字符数组

void ReleaseStringChars(JNIEnv *env, jstring string,
const jchar *chars);

5.1.5 新建UTF-8编码字符串

jstring NewStringUTF(JNIEnv *env, const char *bytes);

5.1.6 获取UTF-8字符串的长度

参考2.11.2
jsize GetStringUTFLength(JNIEnv *env, jstring string);

5.1.7 获取UTF-8编码的Java字符串的

参考2.11.3

const char * GetStringUTFChars(JNIEnv *env, jstring string,
jboolean *isCopy);

5.1.8 释放从UTF-8字符串中获取的字符数组

参考2.11.4

void ReleaseStringUTFChars(JNIEnv *env, jstring string,
const char *utf);

5.1.9 从Java字符串中截取一段字符

如果我们想要从字符串中获取其中的一段内容,可以采用如下方式:

void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);

存在异常

5.1.10 从UTF-8字符串中截取一段字符

参考2.11.9

void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);

5.1.11 直接字符串指针

当我们需要获取字符数组时,使用上面2.11.3和2.11.7的方法都有可能或得到原始字符串的拷贝,很明显这对运行效率有些影响。如果我们能够获得原始字符串的直接指针,就可以极大地优化运行效率。于是JNI提供了Get/ReleaseStringCritical两个函数来操作原始字符串的直接指针。但是对直接指针的操作有着极其严格的限制。这两个函数之间不能存在任何会让线程阻塞的操作。
这两个函数原型如下:

const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);

void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);


5.2 Java数组

5.2.1 获取数组长度

jsize GetArrayLength(JNIEnv *env, jarray array);

5.2.2 新建对象数组

使用如下方法可以创建一个对象数组。

jobjectArray NewObjectArray(JNIEnv *env, jsize length,
jclass elementClass, jobject initialElement);

存在异常

5.2.3 获取对象数组元素

在JNI中获取对象数组元素需要使用下列函数

jobject GetObjectArrayElement(JNIEnv *env,
jobjectArray array, jsize index);

存在异常

5.2.4 设置对象数组元素

void SetObjectArrayElement(JNIEnv *env, jobjectArray array,
jsize index, jobject value);

存在异常

5.2.5 基本数据类型数组

新建基本数据类型数组的函数与2.12.2类似,函数原型为

ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);

具体函数名与返回值类型的关系如下表所示:

函数名 返回数组类型
NewBooleanArray jbooleanArray
NewByteArray jbyteArray
NewCharArray jcharArray
NewShortArray jshortArray
NewIntArray jintArray
NewLongArray jlongArray
NewFloatArray jfloatArray
NewDoubleArray jdoubleArray

获取基本数据类型数组元素的函数原型为

NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, jboolean *isCopy);

具体函数名与返回类型的关系如下表所示:

函数名 参数数组类型 返回值类型
GetBooleanArrayElements jbooleanArray jboolean
GetByteArrayElements jbyteArray jbyte
GetCharArrayElements jcharArray jchar
GetShortArrayElements jshortArray jshort
GetIntArrayElements jintArray jint
GetLongArrayElements jlongArray jlong
GetFloatArrayElements jfloatArray jfloat
GetDoubleArrayElements jdoubleArray jdouble

释放基本数据类型数组

void Release<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, NativeType *elems, jint mode);

mode 行为
0 copy back the content and free the elems buffer
JNI_COMMIT copy back the content but do not free the elems buffer
JNI_ABORT free the buffer without copying back the possible changes
函数名 数组类型 元素类型
ReleaseBooleanArrayElements jbooleanArray jboolean
ReleaseByteArrayElements jbyteArray jbyte
ReleaseCharArrayElements jcharArray jchar
ReleaseShortArrayElements jshortArray jshort
ReleaseIntArrayElements jintArray jint
ReleaseLongArrayElements jlongArray jlong
ReleaseFloatArrayElements jfloatArray jfloat
ReleaseDoubleArrayElements jdoubleArray jdouble

5.2.6 截取数组

详情参考2.11.9,函数原型如下:

void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, NativeType *buf);

函数名 数组类型 数据类型
GetBooleanArrayRegion jbooleanArray jboolean
GetByteArrayRegion jbyteArray jbyte
GetCharArrayRegion jcharArray jchar
GetShortArrayRegion jshortArray jhort
GetIntArrayRegion jintArray jint
GetLongArrayRegion jlongArray jlong
GetFloatArrayRegion jfloatArray jloat
GetDoubleArrayRegion jdoubleArray jdouble

5.2.7 范围设置数组

我们可以通过如下方法给数组的部分赋值

void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, const NativeType *buf);

函数名 数据类型 参数类型
SetBooleanArrayRegion jbooleanArray jboolean
SetByteArrayRegion jbyteArray jbyte
SetCharArrayRegion jcharArray jchar
SetShortArrayRegion jshortArray jshort
SetIntArrayRegion jintArray jint
SetLongArrayRegion jlongArray jlong
SetFloatArrayRegion jfloatArray jfloat
SetDoubleArrayRegion jdoubleArray jdouble

5.2.8 操作基本数据类型数组的直接指针

在某些情况下,我们需要原始数据指针来进行一些操作。调用GetPrimitiveArrayCritical后,我们可以获得一个指向原始数据的指针,但是在调用ReleasePrimitiveArrayCritical函数之前,我们要保证不能进行任何可能会导致线程阻塞的操作。由于GC的运行会打断线程,所以在此期间任何调用GC的线程都会被阻塞。

void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);

jint len = (*env)->GetArrayLength(env, arr1);
  jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, arr1, 0);
  jbyte *a2 = (*env)->GetPrimitiveArrayCritical(env, arr2, 0);
  /* We need to check in case the VM tried to make a copy. */
  if (a1 == NULL || a2 == NULL) {
    ... /* out of memory exception thrown */
  }
  memcpy(a1, a2, len);
  (*env)->ReleasePrimitiveArrayCritical(env, arr2, a2, 0);
  (*env)->ReleasePrimitiveArrayCritical(env, arr1, a1, 0);

下一篇:JNI完全指南(六)——本地方法


[1]ORACLE guides for JNI——Chapter 4: JNI Functions

上一篇 下一篇

猜你喜欢

热点阅读