JNI jstring 操作

6,629 阅读2分钟

通过前面的文章我们知道,jstring 是 Java String 在 JNI 中的代表,但是在 JNI 中,操作 jstring 的方法很少。通常是把 jstring 转换为 char 指针来操作( C语言方式 ),或者把 char 指针转换为 C++ 的 string 类。

创建 jstring

JNI层创建 jstring 对象的方式其实有两种

// 参数 unicodeChars 表示 Unicode 格式字符串
jstring NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);

// 参数 bytes 表示 modified UTF-8 格式字符串
jstring NewStringUTF(JNIEnv *env, const char *bytes);

这种头疼的编码问题,可能让我们不知道选择哪个函数来创建jstring对象? 其实我们只要回答下面的问题,就知道选择哪种函数了。

// 在JNI中,这个字符使用的是哪种编码?
const char * bytes = "hello";

其实在JNI中,默认使用的是 modified UTF-8 编码来表示字符串,因此我们经常使用NewStringUTF() 函数来创建 jstring 对象。

NewStringUTF() 创建成功返回一个 jstring 对象,否则返回 NULL。

通常,我们是从一个 JNI 函数的参数中获取到 jstring 对象,那么什么时候我们需要自己创建 jstring 对象呢? 这个问题的答案就是,当我们执行与 Java 层相关的操作时,并且这个操作需要 String 对象,那么就需要在 JNI 层创建 jstring 对象。例如,在 JNI 层调用 Java 对象的一个方法,这个方法需要一个 String 对象,那么在 JNI 层就需要先创建一个 jstring 对象。

获取jstring长度

jsize GetStringUTFLength(JNIEnv *env, jstring string);

转换jsting为char指针

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

由于JNI操作jstring的函数比较少,有时候我们想要把jstring转换为char指针来操作,这个函数会获取一个代表 jstring 的 char 指针。

参数 isCopy 如果不为 NULL,那么当返回的 char 指针指向的字符串是 jstring 的一个拷贝的时候,*isCopy 的值为 JNI_TRUE,否则为 JNI_FALSE。其实 isCopy 指向的值其实就是相当于一个回调,用来告诉我们是否发生的拷贝。但是通常我们并不关心是否发生了拷贝,因此通常传入 NULL 即可。

函数在失败时,返回 NULL。

使用这个函数需要注意,当这个函数的返回的指针不再需要被使用时,需要使用 ReleaseStringUTFChars() 进行释放,函数原型如下

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

最后一个参数 utf 就是 GetStringUTFChars() 的返回值。

这两个函数是不是有点动态内存分配的味道?

拷贝jstring的一部分

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

这个函数会从参数 str 中,从 start 开始,拷贝 len 长度的字符串,到 buf 中。