2023-01-20 351
我的应用需要使用JNI.逻辑看起来像:
void myJniFunc(JNIEnv *env, jclass clazz, jobjectArray items) {
int count = 10;
struct MyObj *myObjArray = (struct MyObj*)malloc(sizeof(struct MyObj) * count);
for (i = 0; i < count; i++) {
jobject obj = (*env)->GetObjectArrayElement(env, items, i);
jfieldID fieldId = ...;
jstring jstr = (*env)->GetObjectField(env, obj, fieldId);
myObjArray[i].name = (*env)->GetStringUTFChars(env, jstr);
(*env)->DeleteLocalRef(env, obj);
// Location A
}
// some code which will use myObjArray
process(count, myObjectArray);
// Location B
}
和通过jni doc,应使用
重新放映getTringutfchars的数组返回
(*env)->ReleaseStringUTFChars(env, jstr, myObjArray[i].name);
(*env)->ReleaseLocalRef(env, jstr);
我的问题是:
如果我想正确发布JSTRING,该怎么办?
由于您的循环正在创建本地ref(getObjectField),因此您需要在循环中释放它(DeleteLocalRef),否则您将违反本地参考的限制.您必须在两个调用之间完全处理Java字符串.
由于您想将字符串的字节保留在循环外的外部使用,因此您需要复制字节,因为必须在字符串参考为之前释放JVM的固定(或临时副本)(或GetStringutfchars)(getStringutfchars)发行.
因此,循环内部字符串的序列必须为:
注意:使用GetStringUTFChars,您将获得指向Java字符串的修改后的UTF-8编码的指针.这里有两个点:
如果您想使用UTF-16编码,请使用GetStringChars和GetStringLength.在这种情况下,阵列绝对不会终止;它使用内部计数和字符串字节而无需任何转换.
或,如果要更改字符集,则说明真实的” UTF-8″,” ASCII”,” CP437″或” Windows-1252″或其他代码可以处理的其他内容,请使用String.getBytes Overload或Charset类.如果要控制如何处理目标字符集中不支持的字符,请使用Charset类.
经过一些实验,我得到答案,但是我不确定它是否完全正确.
我在循环中删除了JSTRING的引用,错误”添加到JNI本地参考表(有512个条目)”不再发生.
void myJniFunc(JNIEnv *env, jclass clazz, jobjectArray items) {
int count = 10;
jstring tempArray[count];
struct MyObj *myObjArray = (struct MyObj*)malloc(sizeof(struct MyObj) * count);
for (i = 0; i < count; i++) {
jobject obj = (*env)->GetObjectArrayElement(env, items, i);
jfieldID fieldId = ...;
jstring jstr = (*env)->GetObjectField(env, obj, fieldId);
myObjArray[i].name = (*env)->GetStringUTFChars(env, jstr);
(*env)->DeleteLocalRef(env, obj);
// Location A
tempArray[i] = jstr;
(*env)->DeleteLocalRef(jstr);
}
// some code which will use myObjArray
process(count, myObjectArray);
// Location B
for (i = 0; i < count; i++) {
(*env)->ReleaseStringUTFChars(env, tempArray[i], myObjectArray[i].name);
}
}
我关心的是:
函数” Reseasestringutfchars”的第二个参数必须是JSTRING.
因此,我创建一个数组来保留JSTRING的引用以供以后发布.
当我删除循环中Jstring的引用时,这意味着Jstring已被释放.
我在这里的Jstring上有什么问题称为”释放”?
通过我的测试,我没有遇到任何问题.
附加到汤姆·布洛德(Tom Blodget)的帖子,我可以添加: 在jstring对象上使用deletelocalref方法,并且 将Java字符串从Jobights转换为JString首先(例如,当您从Java方法检索字符串时)!将其保留在求职类型引用中,并仅在将其传递给param时才将其转换为JString,否则您将获得” JNI错误(App Bug):访问的Stale local”错误!
例如,不要这样做:
jstring imeiObj = (jstring)env->CallObjectMethod(telephonyManagerObj, jniInfo->jniCache.telephonyManagerClass_getDeviceIdMethod, i);
const char* imeiStr = env->GetStringUTFChars(imeiObj, &isCopy);
env->DeleteLocalRef((jobject)imeiObj);
最好做:
jobject imeiObj = env->CallObjectMethod(telephonyManagerObj, jniInfo->jniCache.telephonyManagerClass_getDeviceIdMethod, i);
const char* imeiStr = env->GetStringUTFChars((jstring)imeiObj, &isCopy);
env->DeleteLocalRef(imeiObj);
我不知道为什么是这样
以上所述是小编给大家介绍的如何在一个循环中正确释放jstring?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/25915.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态