My app needs to use jni. Logic looks like :
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
}
And through JNI doc, the array return by GetStringUTFChars should be relased using
(*env)->ReleaseStringUTFChars(env, jstr, myObjArray[i].name);
(*env)->ReleaseLocalRef(env, jstr);
My question is : What should I do, if I want to release jstring correctly?
Since your loop is creating the local ref (GetObjectField), you need to release it (DeleteLocalRef) in the loop, or you'll run up against the limit on local references. You'll have to completely process the Java string between to two calls.
Since you want to keep the bytes of the string for use outside of the loop, you need to copy the bytes because the JVM's pinning (or temporary copy)(GetStringUTFChars) has to be released (ReleaseStringUTFChars) before the string reference is released.
So the sequence for the string inside the loop must be:
GetObjectField
GetStringUTFChars
ReleaseStringUTFChars
DeleteLocalRef
Note: With GetStringUTFChars
you are getting a pointer to a modified UTF-8 encoding of the Java String. Two points here:
GetStringUTFLength
to get the number of bytes in the modified UTF-8 encoding—not counting any 0-terminator. (Various JNI implementations and The Book do agree that the array is 0-terminated.) If you want to make your own copy with a terminator, be sure to add room for the terminator.If you'd rather use a UTF-16 encoding, use GetStringChars
and GetStringLength
. In this case, the array is definitely not terminated; It uses the internal count and string bytes without any conversion.
Or, if you want to change character sets, to say, real "UTF-8", "ASCII", "CP437" or "Windows-1252" or something else your code can handle, use a String.getBytes
overload or the Charset
class. Use the Charset
class if you want control over how to handle characters that are not supported in the target character set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With