Bug 339947 - Java XPCOM proxies can get used (resurrected) after having been garbage collected causing VM crash. XULRunner only. patch by ttudor/jhpedemonte, r=jhpedemonte.

git-svn-id: svn://10.0.0.236/trunk@199133 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
pedemont%us.ibm.com
2006-06-06 17:13:18 +00:00
parent 2c9f2758e7
commit a81f3bfade
6 changed files with 67 additions and 22 deletions

View File

@@ -62,6 +62,7 @@ jclass stringClass = nsnull;
jclass nsISupportsClass = nsnull;
jclass xpcomExceptionClass = nsnull;
jclass xpcomJavaProxyClass = nsnull;
jclass weakReferenceClass = nsnull;
jmethodID hashCodeMID = nsnull;
jmethodID booleanValueMID = nsnull;
@@ -83,6 +84,9 @@ jmethodID doubleInitMID = nsnull;
jmethodID createProxyMID = nsnull;
jmethodID isXPCOMJavaProxyMID = nsnull;
jmethodID getNativeXPCOMInstMID = nsnull;
jmethodID weakReferenceConstructorMID = nsnull;
jmethodID getReferentMID = nsnull;
jmethodID clearReferentMID = nsnull;
#ifdef DEBUG_JAVAXPCOM
jmethodID getNameMID = nsnull;
@@ -255,6 +259,19 @@ InitializeJavaGlobals(JNIEnv *env)
goto init_error;
}
if (!(clazz = env->FindClass("java/lang/ref/WeakReference")) ||
!(weakReferenceClass = (jclass) env->NewGlobalRef(clazz)) ||
!(weakReferenceConstructorMID = env->GetMethodID(weakReferenceClass,
"<init>","(Ljava/lang/Object;)V")) ||
!(getReferentMID = env->GetMethodID(weakReferenceClass,
"get", "()Ljava/lang/Object;")) ||
!(clearReferentMID = env->GetMethodID(weakReferenceClass,
"clear", "()V")))
{
NS_WARNING("Problem creating java.lang.ref.WeakReference globals");
goto init_error;
}
#ifdef DEBUG_JAVAXPCOM
if (!(clazz = env->FindClass("java/lang/Class")) ||
!(getNameMID = env->GetMethodID(clazz, "getName","()Ljava/lang/String;")))
@@ -392,6 +409,10 @@ FreeJavaGlobals(JNIEnv* env)
env->DeleteGlobalRef(xpcomJavaProxyClass);
xpcomJavaProxyClass = nsnull;
}
if (weakReferenceClass) {
env->DeleteGlobalRef(weakReferenceClass);
weakReferenceClass = nsnull;
}
if (gJavaKeywords) {
delete gJavaKeywords;
@@ -449,7 +470,7 @@ DestroyJavaProxyMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
NativeToJavaProxyMap::ProxyList* item = entry->list;
while(item != nsnull) {
void* xpcom_obj;
jobject javaObject = env->NewLocalRef(item->javaObject);
jobject javaObject = env->CallObjectMethod(item->javaObject, getReferentMID);
rv = GetXPCOMInstFromProxy(env, javaObject, &xpcom_obj);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get XPCOM instance from Java proxy");
@@ -466,6 +487,8 @@ DestroyJavaProxyMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
}
NativeToJavaProxyMap::ProxyList* next = item->next;
env->CallVoidMethod(item->javaObject, clearReferentMID);
env->DeleteGlobalRef(item->javaObject);
delete item;
item = next;
}
@@ -498,11 +521,15 @@ NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
if (!e)
return NS_ERROR_FAILURE;
jweak ref = env->NewWeakGlobalRef(aProxy);
jobject ref = nsnull;
jobject weakRefObj = env->NewObject(weakReferenceClass,
weakReferenceConstructorMID, aProxy);
if (weakRefObj)
ref = env->NewGlobalRef(weakRefObj);
if (!ref)
return NS_ERROR_OUT_OF_MEMORY;
// Add Java proxy ref to start of list
// Add Java proxy weak reference ref to start of list
ProxyList* item = new ProxyList(ref, aIID, e->list);
e->key = aXPCOMObject;
e->list = item;
@@ -538,9 +565,10 @@ NativeToJavaProxyMap::Find(JNIEnv* env, nsISupports* aNativeObject,
ProxyList* item = e->list;
while (item != nsnull && *aResult == nsnull) {
if (item->iid.Equals(aIID)) {
jobject javaObject = env->NewLocalRef(item->javaObject);
if (javaObject) {
*aResult = javaObject;
jobject referentObj = env->CallObjectMethod(item->javaObject,
getReferentMID);
if (!env->IsSameObject(referentObj, NULL)) {
*aResult = referentObj;
#ifdef DEBUG_JAVAXPCOM
char* iid_str = aIID.ToString();
LOG(("< NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
@@ -584,9 +612,8 @@ NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
PR_Free(iid_str);
#endif
jweak weakref = NS_STATIC_CAST(jweak,
NS_CONST_CAST(jobject, item->javaObject));
env->DeleteWeakGlobalRef(weakref);
env->CallVoidMethod(item->javaObject, clearReferentMID);
env->DeleteGlobalRef(item->javaObject);
if (item == e->list) {
e->list = item->next;
if (e->list == nsnull)