我正在学习Java JNI并尝试理解GetStringUTFChars& ReleaseStringUTFChars。仍然我无法理解ReleaseStringUTFChars。 根据我对某篇文章的理解,在大多数情况下,GetStringUTFChars返回对原始字符串数据的引用而不是副本。实际上,ReleaseStringUTFChars释放了jstring或const char *(如果被复制)或两者都发布。
如果我得到以下问题的答案,我可以更好地理解。
在下面的代码中,我是否需要在for循环中调用ReleaseStringUTFChars或仅调用一次(使用任何一个const char *)?
#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]);
}
提前致谢。
答案 0 :(得分:1)
Get/ReleaseStringUTFChars
必须始终成对调用,无论是否返回副本。
在实践中,你几乎总是得到一个副本(至少在我检查的JVM实现中:OpenJDK和Dalvik),以便GC可以自由移动原始数组。 它显然无法收集它,因为你有一个对字符串的引用,但它仍然会移动对象。
还有一个 GetStringCritical/ReleaseStringCritical
调用对,它总是会尝试返回指向原始数组的指针(虽然理论上它仍然可以返回一个副本)。这样可以加快速度,但需要付出代价:在释放数组之前,GC不得移动数组。同样,在实践中,这通常通过与GC建立互斥锁,并递增Get
的锁定计数并将其递减为Release
来实现。这意味着这些必须成对调用,否则锁定计数永远不会回到零,GC可能永远不会运行。 请注意:Get/ReleaseStringCritical
还附带其他与此问题不太相关的限制,但同样重要。