我正在学习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还带有其他限制,这些限制与该问题不太相关,但同样重要。

08-05 04:41