From 9bacd35151b8569ee1b7d70660b930e08d80bac7 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 16 Sep 2014 22:33:42 +0200 Subject: [PATCH] fix problems with JNI references. The C proxy config should hold a weak ref to the java object. Everytime this weak ref has to be used, it must be promoted as a local ref first. --- coreapi/linphonecore_jni.cc | 58 +++++++++++++------------------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 3fd18bed3..768115e32 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -77,24 +77,6 @@ extern "C" void libmswebrtc_init(); return jUserDataObj; \ } -#define RETURN_PROXY_CONFIG_USER_DATA_OBJECT(javaclass, funcprefix, cobj, lc) \ - { \ - jclass jUserDataObjectClass; \ - jmethodID jUserDataObjectCtor; \ - jobject jUserDataObj; \ - jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \ - if (jUserDataObj == NULL) { \ - jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \ - jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"", "(Lorg/linphone/core/LinphoneCoreImpl;J)V"); \ - jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor,lc, (jlong) cobj); \ - jUserDataObj = env->NewWeakGlobalRef(jUserDataObj); \ - funcprefix ## _set_user_data(cobj, jUserDataObj); \ - funcprefix ## _ref(cobj); \ - env->DeleteGlobalRef(jUserDataObjectClass); \ - } \ - return jUserDataObj; \ - } - static JavaVM *jvm=0; static const char* LogDomain = "Linphone"; static jclass handler_class; @@ -478,26 +460,31 @@ public: ,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate), message ? env->NewStringUTF(message) : NULL); } + /* + * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig. + **/ jobject getProxy(JNIEnv *env , LinphoneProxyConfig *proxy, jobject core){ - jobject jobj=0; + jobject jobj=0; - if (proxy!=NULL){ - void *up=linphone_proxy_config_get_user_data(proxy); + if (proxy!=NULL){ + void *up=linphone_proxy_config_get_user_data(proxy); - if (up==NULL){ + if (up==NULL){ + jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); + linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); + linphone_proxy_config_ref(proxy); + }else{ + //promote the weak ref to local ref + jobj=env->NewLocalRef((jobject)up); + if (jobj == NULL){ + //the weak ref was dead jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); - linphone_proxy_config_ref(proxy); - }else{ - jobj=env->NewLocalRef((jobject)up); - if (jobj == NULL){ - jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); - linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); - } } } - return jobj; } + return jobj; + } static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) { JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); @@ -1003,19 +990,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDefaultProxyConfig( J linphone_core_set_default_proxy((LinphoneCore*)lc,(LinphoneProxyConfig*)pc); } -static jobject getOrCreateProxy(JNIEnv* env,LinphoneProxyConfig* proxy,jobject lc){ - RETURN_PROXY_CONFIG_USER_DATA_OBJECT("LinphoneProxyConfigImpl", linphone_proxy_config, proxy, lc); -} - -extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig( JNIEnv* env +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig(JNIEnv* env ,jobject thiz ,jlong lc) { - LinphoneProxyConfig *config=0; LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); linphone_core_get_default_proxy((LinphoneCore*)lc,&config); if(config != 0) { - jobject jproxy = getOrCreateProxy(env,config,lcData->core); + jobject jproxy = lcData->getProxy(env,config,lcData->core); return jproxy; } else { return NULL; @@ -1031,7 +1013,7 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigLi for (int i = 0; i < proxyCount; i++ ) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; - jobject jproxy = getOrCreateProxy(env,proxy,lcData->core); + jobject jproxy = lcData->getProxy(env,proxy,lcData->core); if(jproxy != NULL){ env->SetObjectArrayElement(jProxies, i, jproxy); }