Need some help in understanding when the java string is deleted. On the c side the string is deleted after the call to onCandidates and on the java side setRemoteDescription may take some time to process sdp. How does java sync up to the c side and would it be normal to make a copy of the string before proceeding.
C source code
jstring jstrBuf = (*env)->NewStringUTF(env, sdp);
(*env)->CallVoidMethod(env, onCandidatesCallbackObj, onCandidatesCallback, jstrBuf);
(*env)->DeleteLocalRef(env, jstrBuf);
java code
private void onCandidates(String sdp) {
setRemoteDescription(sdp); // may take time?
}
My code works most of the time but some times my app crashes. Initially this was due to a different thread on the c side. I think my solution is working correctly so now I am considering the life time of the variable.
static void on_gathering_done(juice_agent_t *agent, void *user_ptr) {
LOGI("on_gathering_done");
char sdp[JUICE_MAX_SDP_STRING_LEN];
juice_get_local_description(local_agent, sdp, JUICE_MAX_SDP_STRING_LEN);
JNIEnv *env;
jint res = (*java_vm)->GetEnv(java_vm, (void **) &env, JNI_VERSION_1_6);
// is current thread known?
if (res != JNI_OK) {
LOGI("attaching current thread to VM");
// not known, need to attach
if ((*java_vm)->AttachCurrentThread(java_vm, &env, NULL) == JNI_OK) {
jstring jstrBuf = (*env)->NewStringUTF(env, sdp);
(*env)->CallVoidMethod(env, onCandidatesCallbackObj, onCandidatesCallback, jstrBuf);
(*env)->DeleteLocalRef(env, jstrBuf);
(*java_vm)->DetachCurrentThread(java_vm);
}
} else {
LOGI("thread already attached to VM");
jstring jstrBuf = (*env)->NewStringUTF(env, sdp);
(*env)->CallVoidMethod(env, onCandidatesCallbackObj, onCandidatesCallback, jstrBuf);
(*env)->DeleteLocalRef(env, jstrBuf);
}
}
Thanks Robert
Let's go through your code line by line and think about memory management:
jstring jstrBuf = (*env)->NewStringUTF(env, sdp);
This line creates a Java String object on the heap by copying from sdp
. It only has one reference, namely the JNI-local reference here in jstrBuf
.
(*env)->CallVoidMethod(env, onCandidatesCallbackObj, onCandidatesCallback, jstrBuf);
This line passes jstrBuf
to your Java method. Method parameters are garbage collection roots, so there is an extra reference to your object from the call stack.
(*env)->DeleteLocalRef(env, jstrBuf);
This line removes your JNI-held local reference.
At this point either setRemoteDescription
created an additional reference (eg by storing sdp
somewhere or taking a substring of it, or it did not.
In the second case jstrBuf
will no longer have references to it and the memory for it will be freed when the garbage collector runs again.