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.
This commit is contained in:
Simon Morlat 2014-09-16 22:33:42 +02:00
parent 4bc67e3645
commit 9bacd35151

View file

@ -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,"<init>", "(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);
}