зеркало из https://github.com/mozilla/pjs.git
Fix several memory leaks. Also, use monitors around sensetive structures.
Original committer: pedemont%us.ibm.com Original revision: 1.29 Original date: 2005/02/24 23:17:36
This commit is contained in:
Родитель
0ada46f4ec
Коммит
1398fe4f44
|
@ -89,7 +89,7 @@ jmethodID proxyToStringMID = nsnull;
|
||||||
NativeToJavaProxyMap* gNativeToJavaProxyMap = nsnull;
|
NativeToJavaProxyMap* gNativeToJavaProxyMap = nsnull;
|
||||||
JavaToXPTCStubMap* gJavaToXPTCStubMap = nsnull;
|
JavaToXPTCStubMap* gJavaToXPTCStubMap = nsnull;
|
||||||
|
|
||||||
PRLock* gJavaXPCOMLock = nsnull;
|
PRMonitor* gJavaXPCOMMonitor = nsnull;
|
||||||
|
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
|
@ -98,7 +98,7 @@ PRLock* gJavaXPCOMLock = nsnull;
|
||||||
PRBool
|
PRBool
|
||||||
InitializeJavaGlobals(JNIEnv *env)
|
InitializeJavaGlobals(JNIEnv *env)
|
||||||
{
|
{
|
||||||
if (gJavaXPCOMLock)
|
if (gJavaXPCOMMonitor)
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
|
|
||||||
jclass clazz;
|
jclass clazz;
|
||||||
|
@ -244,7 +244,7 @@ InitializeJavaGlobals(JNIEnv *env)
|
||||||
goto init_error;
|
goto init_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
gJavaXPCOMLock = PR_NewLock();
|
gJavaXPCOMMonitor = nsAutoMonitor::NewMonitor("Javaconnect Monitor");
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
|
|
||||||
init_error:
|
init_error:
|
||||||
|
@ -260,8 +260,22 @@ init_error:
|
||||||
void
|
void
|
||||||
FreeJavaGlobals(JNIEnv* env)
|
FreeJavaGlobals(JNIEnv* env)
|
||||||
{
|
{
|
||||||
PR_Lock(gJavaXPCOMLock);
|
PR_EnterMonitor(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
|
// Free the mappings first, since that process depends on some of the Java
|
||||||
|
// globals that are freed later.
|
||||||
|
if (gNativeToJavaProxyMap) {
|
||||||
|
gNativeToJavaProxyMap->Destroy(env);
|
||||||
|
delete gNativeToJavaProxyMap;
|
||||||
|
gNativeToJavaProxyMap = nsnull;
|
||||||
|
}
|
||||||
|
if (gJavaToXPTCStubMap) {
|
||||||
|
gJavaToXPTCStubMap->Destroy();
|
||||||
|
delete gJavaToXPTCStubMap;
|
||||||
|
gJavaToXPTCStubMap = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free remaining Java globals
|
||||||
if (booleanClass) {
|
if (booleanClass) {
|
||||||
env->DeleteGlobalRef(booleanClass);
|
env->DeleteGlobalRef(booleanClass);
|
||||||
booleanClass = nsnull;
|
booleanClass = nsnull;
|
||||||
|
@ -311,18 +325,9 @@ FreeJavaGlobals(JNIEnv* env)
|
||||||
xpcomJavaProxyClass = nsnull;
|
xpcomJavaProxyClass = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gNativeToJavaProxyMap) {
|
PR_ExitMonitor(gJavaXPCOMMonitor);
|
||||||
delete gNativeToJavaProxyMap;
|
nsAutoMonitor::DestroyMonitor(gJavaXPCOMMonitor);
|
||||||
gNativeToJavaProxyMap = nsnull;
|
gJavaXPCOMMonitor = nsnull;
|
||||||
}
|
|
||||||
if (gJavaToXPTCStubMap) {
|
|
||||||
delete gJavaToXPTCStubMap;
|
|
||||||
gJavaToXPTCStubMap = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
PR_Unlock(gJavaXPCOMLock);
|
|
||||||
PR_DestroyLock(gJavaXPCOMLock);
|
|
||||||
gJavaXPCOMLock = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -348,11 +353,6 @@ static PLDHashTableOps hash_ops =
|
||||||
// So we optimize the common case by using a hash table. Then, if there are
|
// So we optimize the common case by using a hash table. Then, if there are
|
||||||
// multiple Java proxies, we cycle through the linked list, comparing IIDs.
|
// multiple Java proxies, we cycle through the linked list, comparing IIDs.
|
||||||
|
|
||||||
NativeToJavaProxyMap::~NativeToJavaProxyMap()
|
|
||||||
{
|
|
||||||
PL_DHashTableDestroy(mHashTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NativeToJavaProxyMap::Init()
|
NativeToJavaProxyMap::Init()
|
||||||
{
|
{
|
||||||
|
@ -362,10 +362,61 @@ NativeToJavaProxyMap::Init()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PLDHashOperator
|
||||||
|
DestroyJavaProxyMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
|
||||||
|
PRUint32 aNumber, void* aData)
|
||||||
|
{
|
||||||
|
JNIEnv* env = NS_STATIC_CAST(JNIEnv*, aData);
|
||||||
|
NativeToJavaProxyMap::Entry* entry =
|
||||||
|
NS_STATIC_CAST(NativeToJavaProxyMap::Entry*, aHeader);
|
||||||
|
|
||||||
|
// first, delete XPCOM instances from the Java proxies
|
||||||
|
nsresult rv;
|
||||||
|
NativeToJavaProxyMap::ProxyList* item = entry->list;
|
||||||
|
while(item != nsnull) {
|
||||||
|
void* xpcom_obj;
|
||||||
|
jobject javaObject = env->NewLocalRef(item->javaObject);
|
||||||
|
rv = GetXPCOMInstFromProxy(env, javaObject, &xpcom_obj);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get XPCOM instance from Java proxy");
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
|
||||||
|
#ifdef DEBUG_JAVAXPCOM
|
||||||
|
char* iid_str = item->iid.ToString();
|
||||||
|
LOG(("- NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
|
(PRUint32) env->CallIntMethod(javaObject, hashCodeMID),
|
||||||
|
(PRUint32) entry, iid_str));
|
||||||
|
PR_Free(iid_str);
|
||||||
|
#endif
|
||||||
|
delete inst; // releases native XPCOM object
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeToJavaProxyMap::ProxyList* next = item->next;
|
||||||
|
delete item;
|
||||||
|
item = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
NativeToJavaProxyMap::Destroy(JNIEnv* env)
|
||||||
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
|
PL_DHashTableEnumerate(mHashTable, DestroyJavaProxyMappingEnum, env);
|
||||||
|
PL_DHashTableDestroy(mHashTable);
|
||||||
|
mHashTable = nsnull;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
|
NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
|
||||||
const nsIID& aIID, jobject aProxy)
|
const nsIID& aIID, jobject aProxy)
|
||||||
{
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
||||||
aXPCOMObject,
|
aXPCOMObject,
|
||||||
PL_DHASH_ADD));
|
PL_DHASH_ADD));
|
||||||
|
@ -384,7 +435,8 @@ NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
|
||||||
#ifdef DEBUG_JAVAXPCOM
|
#ifdef DEBUG_JAVAXPCOM
|
||||||
char* iid_str = aIID.ToString();
|
char* iid_str = aIID.ToString();
|
||||||
LOG(("+ NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
LOG(("+ NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
env->CallIntMethod(aProxy, hashCodeMID), (int) aXPCOMObject, iid_str));
|
(PRUint32) env->CallIntMethod(aProxy, hashCodeMID),
|
||||||
|
(PRUint32) aXPCOMObject, iid_str));
|
||||||
PR_Free(iid_str);
|
PR_Free(iid_str);
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -398,6 +450,8 @@ NativeToJavaProxyMap::Find(JNIEnv* env, nsISupports* aNativeObject,
|
||||||
if (!aResult)
|
if (!aResult)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
*aResult = nsnull;
|
*aResult = nsnull;
|
||||||
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
||||||
aNativeObject,
|
aNativeObject,
|
||||||
|
@ -415,8 +469,8 @@ NativeToJavaProxyMap::Find(JNIEnv* env, nsISupports* aNativeObject,
|
||||||
#ifdef DEBUG_JAVAXPCOM
|
#ifdef DEBUG_JAVAXPCOM
|
||||||
char* iid_str = aIID.ToString();
|
char* iid_str = aIID.ToString();
|
||||||
LOG(("< NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
LOG(("< NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
env->CallIntMethod(*aResult, hashCodeMID),
|
(PRUint32) env->CallIntMethod(*aResult, hashCodeMID),
|
||||||
(int) aNativeObject, iid_str));
|
(PRUint32) aNativeObject, iid_str));
|
||||||
PR_Free(iid_str);
|
PR_Free(iid_str);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -431,6 +485,8 @@ nsresult
|
||||||
NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
|
NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
|
||||||
const nsIID& aIID)
|
const nsIID& aIID)
|
||||||
{
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
||||||
aNativeObject,
|
aNativeObject,
|
||||||
PL_DHASH_LOOKUP));
|
PL_DHASH_LOOKUP));
|
||||||
|
@ -447,8 +503,8 @@ NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
|
||||||
#ifdef DEBUG_JAVAXPCOM
|
#ifdef DEBUG_JAVAXPCOM
|
||||||
char* iid_str = aIID.ToString();
|
char* iid_str = aIID.ToString();
|
||||||
LOG(("- NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
LOG(("- NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
env->CallIntMethod(item->javaObject, hashCodeMID),
|
(PRUint32) env->CallIntMethod(item->javaObject, hashCodeMID),
|
||||||
(int) aNativeObject, iid_str));
|
(PRUint32) aNativeObject, iid_str));
|
||||||
PR_Free(iid_str);
|
PR_Free(iid_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -473,11 +529,6 @@ NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaToXPTCStubMap::~JavaToXPTCStubMap()
|
|
||||||
{
|
|
||||||
PL_DHashTableDestroy(mHashTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
JavaToXPTCStubMap::Init()
|
JavaToXPTCStubMap::Init()
|
||||||
{
|
{
|
||||||
|
@ -487,9 +538,39 @@ JavaToXPTCStubMap::Init()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PLDHashOperator
|
||||||
|
DestroyXPTCMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
|
||||||
|
PRUint32 aNumber, void* aData)
|
||||||
|
{
|
||||||
|
JavaToXPTCStubMap::Entry* entry =
|
||||||
|
NS_STATIC_CAST(JavaToXPTCStubMap::Entry*, aHeader);
|
||||||
|
|
||||||
|
// The XPTC stub will be released by the XPCOM side, if it hasn't been
|
||||||
|
// already. We just need to delete the Java global ref held by the XPTC stub,
|
||||||
|
// so the Java garbage collector can handle the Java object when necessary.
|
||||||
|
entry->xptcstub->DeleteStrongRef();
|
||||||
|
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
JavaToXPTCStubMap::Destroy()
|
||||||
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
|
PL_DHashTableEnumerate(mHashTable, DestroyXPTCMappingEnum, nsnull);
|
||||||
|
PL_DHashTableDestroy(mHashTable);
|
||||||
|
mHashTable = nsnull;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
JavaToXPTCStubMap::Add(JNIEnv* env, jobject aJavaObject, nsJavaXPTCStub* aProxy)
|
JavaToXPTCStubMap::Add(JNIEnv* env, jobject aJavaObject, nsJavaXPTCStub* aProxy)
|
||||||
{
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
||||||
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
||||||
NS_INT32_TO_PTR(hash),
|
NS_INT32_TO_PTR(hash),
|
||||||
|
@ -509,7 +590,7 @@ JavaToXPTCStubMap::Add(JNIEnv* env, jobject aJavaObject, nsJavaXPTCStub* aProxy)
|
||||||
iface_info->GetInterfaceIID(&iid);
|
iface_info->GetInterfaceIID(&iid);
|
||||||
char* iid_str = iid->ToString();
|
char* iid_str = iid->ToString();
|
||||||
LOG(("+ JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
LOG(("+ JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
hash, (int) aProxy, iid_str));
|
(PRUint32) hash, (PRUint32) aProxy, iid_str));
|
||||||
PR_Free(iid_str);
|
PR_Free(iid_str);
|
||||||
nsMemory::Free(iid);
|
nsMemory::Free(iid);
|
||||||
NS_RELEASE(iface_info);
|
NS_RELEASE(iface_info);
|
||||||
|
@ -525,6 +606,8 @@ JavaToXPTCStubMap::Find(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
|
||||||
if (!aResult)
|
if (!aResult)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
*aResult = nsnull;
|
*aResult = nsnull;
|
||||||
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
||||||
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
|
||||||
|
@ -540,7 +623,7 @@ JavaToXPTCStubMap::Find(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
char* iid_str = aIID.ToString();
|
char* iid_str = aIID.ToString();
|
||||||
LOG(("< JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
LOG(("< JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
|
||||||
hash, (int) *aResult, iid_str));
|
(PRUint32) hash, (PRUint32) *aResult, iid_str));
|
||||||
PR_Free(iid_str);
|
PR_Free(iid_str);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -554,11 +637,13 @@ JavaToXPTCStubMap::Find(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
|
||||||
nsresult
|
nsresult
|
||||||
JavaToXPTCStubMap::Remove(JNIEnv* env, jobject aJavaObject)
|
JavaToXPTCStubMap::Remove(JNIEnv* env, jobject aJavaObject)
|
||||||
{
|
{
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
|
||||||
PL_DHashTableOperate(mHashTable, NS_INT32_TO_PTR(hash), PL_DHASH_REMOVE);
|
PL_DHashTableOperate(mHashTable, NS_INT32_TO_PTR(hash), PL_DHASH_REMOVE);
|
||||||
|
|
||||||
#ifdef DEBUG_JAVAXPCOM
|
#ifdef DEBUG_JAVAXPCOM
|
||||||
LOG(("- JavaToXPTCStubMap (Java=%08x)\n", hash));
|
LOG(("- JavaToXPTCStubMap (Java=%08x)\n", (PRUint32) hash));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -617,6 +702,8 @@ GetNewOrUsedJavaObject(JNIEnv* env, nsISupports* aXPCOMObject,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
// Get associated Java object from hash table
|
// Get associated Java object from hash table
|
||||||
rv = gNativeToJavaProxyMap->Find(env, aXPCOMObject, aIID, aResult);
|
rv = gNativeToJavaProxyMap->Find(env, aXPCOMObject, aIID, aResult);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
|
@ -664,6 +751,8 @@ GetNewOrUsedXPCOMObject(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoMonitor mon(gJavaXPCOMMonitor);
|
||||||
|
|
||||||
*aIsXPTCStub = PR_TRUE;
|
*aIsXPTCStub = PR_TRUE;
|
||||||
|
|
||||||
nsJavaXPTCStub* stub;
|
nsJavaXPTCStub* stub;
|
||||||
|
@ -809,6 +898,16 @@ ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage)
|
||||||
}
|
}
|
||||||
methodSig.AppendLiteral(")V");
|
methodSig.AppendLiteral(")V");
|
||||||
|
|
||||||
|
// In some instances (such as in shutdownXPCOM() and termEmbedding()), we
|
||||||
|
// will need to throw an exception when Javaconnect has already been
|
||||||
|
// terminated. In such a case, 'xpcomExceptionClass' will be null. So we
|
||||||
|
// reset it temporarily in order to throw the appropriate exception.
|
||||||
|
if (xpcomExceptionClass == nsnull) {
|
||||||
|
xpcomExceptionClass = env->FindClass("org/mozilla/xpcom/XPCOMException");
|
||||||
|
if (!xpcomExceptionClass)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// create exception object
|
// create exception object
|
||||||
jthrowable throwObj = nsnull;
|
jthrowable throwObj = nsnull;
|
||||||
jmethodID mid = env->GetMethodID(xpcomExceptionClass, "<init>",
|
jmethodID mid = env->GetMethodID(xpcomExceptionClass, "<init>",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче