我正在学习Java JNI,并试图了解GetStringUTFChars和ReleaseStringUTFChars。仍然我无法理解ReleaseStringUTFChars。
根据我对某些文章的理解,在大多数情况下,GetStringUTFChars返回对原始字符串数据的引用,而不是对副本的引用。因此,实际上ReleaseStringUTFChars会释放jstring或const char *(如果已复制)或两者。
如果我得到以下问题的答案,我可以得到更好的理解。
在下面的代码中,我是否需要在for循环中或仅一次(使用const char *中的任何一个)调用ReleaseStringUTFChars?
#define array_size 10
const char* chr[array_size];
jboolean blnIsCopy;
for (int i = 0; i < array_size; i++) {
chr[i] = env->GetStringUTFChars(myjstring, &blnIsCopy);
printf((bool)blnIsCopy ? "true\n" : "false\n"); //displays always true
printf("Address = %p\n\n",chr[i]); //displays different address
}
//ReleaseStringUTFChars with in a for loop or single statement is enough
for (int i = 0; i < array_size; i++) {
env->ReleaseStringUTFChars(myjstring, chr[i]);
}
提前致谢。
最佳答案
Get/ReleaseStringUTFChars
必须始终成对调用,无论是否返回副本。
实际上,您几乎总是会得到一个副本(至少使用我检查过的JVM实现:OpenJDK和Dalvik),以便GC可以自由移动原始数组。它显然无法收集它,因为您已经对该字符串进行了引用,但是它仍然会移动对象。
还有一个GetStringCritical/ReleaseStringCritical
调用对,它将始终尝试返回一个指向原始数组的指针(尽管理论上它可能仍返回一个副本)。这样可以使其更快,但要付出一定的代价:GC必须在释放阵列之前才移动阵列。同样,在实践中,这通常是通过与GC建立互斥体,并为Get
增加锁计数,为Release
减少锁计数来实现的。这意味着它们也必须成对调用,否则锁定计数将永远不会回到零,并且GC可能永远不会运行。请注意:Get/ReleaseStringCritical
还带有其他限制,这些限制与该问题不太相关,但同样重要。