java char 指针数组_JNI完全指南(五)——字符串与数组

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

JNI完全指南版本:1

作者:陈小默

声明:禁止商业,禁止转载

五、字符串与数组

5.1 Java字符串

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

jstring NewString(JNIEnv *env, const jchar *unicodeChars,

jsize len);

unicodeChars:一个指向Unicode编码的字符数组的指针。

len:unicodeChars的长度

return:Java字符串对象

存在异常

OutOfMemoryError

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

jsize GetStringLength(JNIEnv *env, jstring string);

string:Java字符串对象

return:字符串长度

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

const jchar * GetStringChars(JNIEnv *env, jstring string,

jboolean *isCopy);

isCopy:注意,这个参数很重要,这是一个指向Java布尔类型的指针。函数返回之后应当检查这个参数的值,如果值为JNI_TRUE表示返回的字符是Java字符串的拷贝,我们可以对其中的值进行任意修改。如果返回值为JNI_FALSE,表示这个字符指针指向原始Java字符串的内存,这时候对字符数组的任何修改都将会原始字符串的内容。如果你不关心字符数组的来源,或者说你的操作不会对字符数组进行任何修改,可以传入NULL。

return:指向字节数组的指针

5.1.4 释放从Java字符串中获取的字符数组void ReleaseStringChars(JNIEnv *env, jstring string,

const jchar *chars);

string:Java字符串对象。

chars:字符数组。

5.1.5 新建UTF-8编码字符串jstring NewStringUTF(JNIEnv *env, const char *bytes);

bytes:UTF-8编码的字节数组。

return:UTF-8编码的Java字符串对象

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);

str:Java字符串对象。

start:起始位置。

len:截取长度。

buf:保存截取结果的缓冲区。

存在异常

StringIndexOutOfBoundsException

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);

length:数组的长度。

elementClass:数组中的对象类型。

initialElement:数组中的每个元素都会使用这个值进行初始化,可以为NULL。

return:对象数组,创建失败返回NULL

存在异常

OutOfMemoryError

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

jobject GetObjectArrayElement(JNIEnv *env,

jobjectArray array, jsize index);

array:对象数组

index:位置索引

存在异常

ArrayIndexOutOfBoundsException

5.2.4 设置对象数组元素void SetObjectArrayElement(JNIEnv *env, jobjectArray array,

jsize index, jobject value);

存在异常

ArrayIndexOutOfBoundsException

ArrayStoreException:传入的值与数组类型不一致

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

ArrayType NewArray(JNIEnv *env, jsize length);

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

返回数组类型

NewBooleanArray

jbooleanArray

NewByteArray

jbyteArray

NewCharArray

jcharArray

NewShortArray

jshortArray

NewIntArray

jintArray

NewLongArray

jlongArray

NewFloatArray

jfloatArray

NewDoubleArray

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

NativeType *GetArrayElements(JNIEnv *env,

ArrayType array, jboolean *isCopy);

isCopy:参考2.11.3

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

参数数组类型

返回值类型

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 ReleaseArrayElements(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 GetArrayRegion(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 SetArrayRegion(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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值