You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/10/16 08:10:54 UTC
svn commit: r585052 - in /openejb/trunk/openejb3: ./
container/openejb-core/src/main/java/org/apache/openejb/
container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/
server/openejb-client/src/main/java/org/apache/openejb/client/
Author: dain
Date: Mon Oct 15 23:10:53 2007
New Revision: 585052
URL: http://svn.apache.org/viewvc?rev=585052&view=rev
Log:
fixed some memory leaks in Client EJBInvocationHandler and with Sun vm class loader caches
upgraded to commons-logging 1.1 which reduces class loader leaks
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
openejb/trunk/openejb3/pom.xml
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java?rev=585052&r1=585051&r2=585052&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java Mon Oct 15 23:10:53 2007
@@ -17,16 +17,63 @@
*/
package org.apache.openejb;
+import java.beans.Introspector;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+
/**
* @version $Revision$ $Date$
*/
public class ClassLoaderUtil {
public static ClassLoader getContextClassLoader() {
- return (ClassLoader) java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
- public Object run() {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
+ }
+
+ /**
+ * Cleans well known class loader leaks in VMs and libraries. There is a lot of bad code out there and this method
+ * will clear up the know problems. This method should only be called when the class loader will no longer be used.
+ * It this method is called two often it can have a serious impact on preformance.
+ * @param classLoader the class loader to destroy
+ */
+ public static void clearClassLoaderCaches() {
+ clearSunSoftCache(ObjectInputStream.class, "subclassAudits");
+ clearSunSoftCache(ObjectOutputStream.class, "subclassAudits");
+ clearSunSoftCache(ObjectStreamClass.class, "localDescs");
+ clearSunSoftCache(ObjectStreamClass.class, "reflectors");
+ Introspector.flushCaches();
+ }
+
+ /**
+ * Clears the caches maintained by the SunVM object stream implementation. This method uses reflection and
+ * setAccessable to obtain access to the Sun cache. The cache is locked with a synchronize monitor and cleared.
+ * This method completely clears the class loader cache which will impact preformance of object serialization.
+ * @param clazz the name of the class containing the cache field
+ * @param fieldName the name of the cache field
+ */
+ public static void clearSunSoftCache(Class clazz, String fieldName) {
+ Map cache = null;
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ cache = (Map) field.get(null);
+ } catch (Throwable ignored) {
+ // there is nothing a user could do about this anyway
+ }
+
+ if (cache != null) {
+ synchronized (cache) {
+ cache.clear();
+ }
+ }
}
}
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=585052&r1=585051&r2=585052&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Mon Oct 15 23:10:53 2007
@@ -26,6 +26,7 @@
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.UndeployException;
import org.apache.openejb.BeanType;
+import org.apache.openejb.ClassLoaderUtil;
import org.apache.openejb.resource.GeronimoConnectionManagerFactory;
import org.apache.openejb.core.ConnectorReference;
import org.apache.openejb.core.CoreContainerSystem;
@@ -665,6 +666,9 @@
undeployException.getCauses().add(new Exception("client: " + clientId + ": " + t.getMessage(), t));
}
}
+
+ ClassLoaderUtil.clearClassLoaderCaches();
+
if (undeployException.getCauses().size() > 0) {
throw undeployException;
}
Modified: openejb/trunk/openejb3/pom.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/pom.xml?rev=585052&r1=585051&r2=585052&view=diff
==============================================================================
--- openejb/trunk/openejb3/pom.xml (original)
+++ openejb/trunk/openejb3/pom.xml Mon Oct 15 23:10:53 2007
@@ -357,12 +357,12 @@
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
- <version>1.0.4</version>
+ <version>1.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.0.4</version>
+ <version>1.1</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java?rev=585052&r1=585051&r2=585052&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java Mon Oct 15 23:10:53 2007
@@ -18,12 +18,14 @@
import java.io.Serializable;
import java.lang.reflect.Method;
+import java.lang.ref.WeakReference;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.AccessException;
-import java.rmi.Remote;
import java.util.HashSet;
-import java.util.Hashtable;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.apache.openejb.client.proxy.InvocationHandler;
@@ -31,7 +33,6 @@
import javax.transaction.TransactionRolledbackException;
import javax.ejb.TransactionRequiredLocalException;
import javax.ejb.TransactionRolledbackLocalException;
-import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.AccessLocalException;
import javax.ejb.EJBException;
import javax.ejb.EJBAccessException;
@@ -45,7 +46,7 @@
protected static final Method HASHCODE = getMethod(Object.class, "hashCode");
protected static final Method TOSTRING = getMethod(Object.class, "toString");
- protected static final Hashtable<Object,HashSet> liveHandleRegistry = new Hashtable();
+ protected static final ConcurrentMap<Object, Set<WeakReference<EJBInvocationHandler>>> liveHandleRegistry = new ConcurrentHashMap<Object, Set<WeakReference<EJBInvocationHandler>>>();
protected transient boolean inProxyMap = false;
@@ -145,27 +146,32 @@
protected static void invalidateAllHandlers(Object key) {
- HashSet<EJBInvocationHandler> set = liveHandleRegistry.remove(key);
+ Set<WeakReference<EJBInvocationHandler>> set = liveHandleRegistry.remove(key);
if (set == null) return;
synchronized (set) {
- for (EJBInvocationHandler handler : set) {
- handler.invalidateReference();
+ for (WeakReference<EJBInvocationHandler> ref : set) {
+ EJBInvocationHandler handler = ref.get();
+ if (handler != null) {
+ handler.invalidateReference();
+ }
}
set.clear();
}
}
protected static void registerHandler(Object key, EJBInvocationHandler handler) {
- HashSet set = (HashSet) liveHandleRegistry.get(key);
+ Set<WeakReference<EJBInvocationHandler>> set = liveHandleRegistry.get(key);
if (set == null) {
- set = new HashSet();
- liveHandleRegistry.put(key, set);
+ set = new HashSet<WeakReference<EJBInvocationHandler>>();
+ Set<WeakReference<EJBInvocationHandler>> current = liveHandleRegistry.putIfAbsent(key, set);
+ // someone else added the set
+ if (current != null) set = current;
}
synchronized (set) {
- set.add(handler);
+ set.add(new WeakReference<EJBInvocationHandler>(handler));
}
}