1. 简介
JNI 中 GetStringUTFChars
和 ReleaseStringUTFChars
是用于获取和释放 Java 字符串的 C/C++ 字符串指针的函数。
2. GetStringUTFChars
函数
GetStringUTFChars
函数用于获取 Java 字符串的 C/C++ 字符串指针。该指针指向一个以 null 结尾的 UTF-8 编码的字符串。
函数原型:
const char *GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy);
参数:
env
: JNIEnv 指针,用于访问 JVM 环境。str
: 要获取的 Java 字符串对象。isCopy
: 指向一个布尔值的指针,用于指示返回值是否为字符串的副本。
返回值:
- 如果成功,则返回指向 UTF-8 编码字符串的指针。
- 如果失败,则返回 NULL。
3. ReleaseStringUTFChars
函数
ReleaseStringUTFChars
函数用于释放 GetStringUTFChars
返回的指针。当您不再需要使用该指针时,必须调用 ReleaseStringUTFChars
函数来释放它,否则会导致内存泄漏。
函数原型:
void ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars);
参数:
env
: JNIEnv 指针,用于访问 JVM 环境。str
: 要释放的 Java 字符串对象。chars
: 由GetStringUTFChars
返回的指针。
4. 非拷贝方式和是否需要释放
GetStringUTFChars
函数有两种方式获取 Java 字符串
- 拷贝方式: 函数创建一个字符串的副本,并返回指向副本的指针。
- 非拷贝方式: 函数直接返回指向 Java 字符串内部存储的指针。
是否需要调用 ReleaseStringUTFChars
取决于 GetStringUTFChars
函数使用的获取方式:
- 拷贝方式: 必须 调用
ReleaseStringUTFChars
来释放副本,否则会导致内存泄漏。 - 非拷贝方式: 不需要 调用
ReleaseStringUTFChars
,因为您使用的是 Java 字符串内部的指针,无需释放。
如何判断是否为拷贝方式?
- 检查
isCopy
参数的值:如果isCopy
为JNI_TRUE
,则表示使用了拷贝方式;如果isCopy
为JNI_FALSE
,则表示使用了非拷贝方式。
5. 示例
#include <jni.h>
#include <stdio.h>
JNIEXPORT jstring JNICALL Java_com_example_MyClass_getString(JNIEnv *env, jobject obj, jstring str) {
jboolean isCopy;
const char *cStr = GetStringUTFChars(env, str, &isCopy);
if (isCopy) {
// 使用拷贝方式获取,需要释放
printf("拷贝方式获取:%s\n", cStr);
ReleaseStringUTFChars(env, str, cStr);
} else {
// 使用非拷贝方式获取,不需要释放
printf("非拷贝方式获取:%s\n", cStr);
}
return (*env)->NewStringUTF(env, cStr);
}
上面的printf在jni里不能打印,看不见日志,自行替换成Androidlog。
总结
- 始终使用
ReleaseStringUTFChars
函数来释放GetStringUTFChars
返回的指针,除非isCopy
参数为JNI_FALSE
。 - 始终检查
isCopy
参数的值,以确保您知道何时需要释放指针。