Hi,

This can be problematic:

+ private static WeakHashMap cache = new WeakHashMap<String, Object>();

Please note the key is String. Unless the string is interned [1], the key can be GCed even when the class is active.

Another problem is that code now uses hashCode (int) as the key. The compiler doesn't complain as the cache is defined as "WeakHashMap cache". The map should be changed to:

private static WeakHashMap<Integer, Object> cache = new WeakHashMap<Integer, Object>();

[1] http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern()

Thanks,
Raymond
--------------------------------------------------
From: <[email protected]>
Sent: Wednesday, October 21, 2009 9:27 AM
To: <[email protected]>
Subject: svn commit: r828086 - in /tuscany/branches/sca-java-1.5.2/modules: core/src/main/java/org/apache/tuscany/sca/core/invocation/ implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/ interface/src/main/java/org/apache/tuscany/...

Author: slaws
Date: Wed Oct 21 16:27:30 2009
New Revision: 828086

URL: http://svn.apache.org/viewvc?rev=828086&view=rev
Log:
TUSCANY-3312 remove circular references where a class is used as the key of a map and the value of the map also references the class. The weakness of the map never comes into play as there is always a reference to the key (held by the value). This all pins the app classloader and causes a leak on each app start/stop cycle

Modified:

tuscany/branches/sca-java-1.5.2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/SCAProxy.java

tuscany/branches/sca-java-1.5.2/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java

tuscany/branches/sca-java-1.5.2/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java

Modified: tuscany/branches/sca-java-1.5.2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/SCAProxy.java URL: http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.5.2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/SCAProxy.java?rev=828086&r1=828085&r2=828086&view=diff
==============================================================================
--- tuscany/branches/sca-java-1.5.2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/SCAProxy.java (original) +++ tuscany/branches/sca-java-1.5.2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/SCAProxy.java Wed Oct 21 16:27:30 2009
@@ -33,7 +33,7 @@
// This is a cache containing the proxy class constructor for each business interface. // This improves performance compared to calling Proxy.newProxyInstance()
     // every time that a proxy is needed.
-     private static WeakHashMap cache = new WeakHashMap<Class, Object>();
+ private static WeakHashMap cache = new WeakHashMap<String, Object>();

public static Object newProxyInstance(ClassLoader classloader, Class aclass[], InvocationHandler invocationhandler)
        throws IllegalArgumentException
@@ -44,13 +44,13 @@
// Lookup cached constructor. aclass[0] is the reference's business interface.
            Constructor proxyCTOR;
            synchronized(cache) {
-                proxyCTOR = (Constructor) cache.get(aclass[0]);
+ proxyCTOR = (Constructor) cache.get(aclass[0].hashCode());
            }
            if(proxyCTOR == null) {
                Class proxyClass = getProxyClass(classloader, aclass);
                proxyCTOR = proxyClass.getConstructor(constructorParams);
                synchronized(cache){
-                    cache.put(aclass[0],proxyCTOR);
+                    cache.put(aclass[0].hashCode(),proxyCTOR);
                }
            }
return proxyCTOR.newInstance(new Object[] { invocationhandler });

Modified: tuscany/branches/sca-java-1.5.2/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java URL: http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.5.2/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java?rev=828086&r1=828085&r2=828086&view=diff
==============================================================================
--- tuscany/branches/sca-java-1.5.2/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java (original) +++ tuscany/branches/sca-java-1.5.2/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java Wed Oct 21 16:27:30 2009
@@ -21,6 +21,7 @@

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
+import java.lang.ref.WeakReference;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -36,8 +37,8 @@
public class JavaElementImpl {
    private AnnotatedElement anchor;
    private ElementType elementType;
-    private Class<?> type;
-    private Type genericType;
+    private WeakReference<Class<?>> type;
+    private WeakReference<Type> genericType;
    private int index = -1;
    private String name;
    private Class<? extends Annotation> classifer;
@@ -51,24 +52,24 @@
    public JavaElementImpl(Class<?> cls) {
        this.anchor = cls;
        this.elementType = ElementType.TYPE;
-        this.type = cls;
-        this.genericType = cls;
+        this.type = new WeakReference<Class<?>>(cls);
+        this.genericType = new WeakReference<Type>(cls);
        this.name = cls.getName();
    }

    public JavaElementImpl(Field field) {
        this.anchor = field;
        this.elementType = ElementType.FIELD;
-        this.type = field.getType();
-        this.genericType = field.getGenericType();
+        this.type = new WeakReference<Class<?>>(field.getType());
+ this.genericType = new WeakReference<Type>(field.getGenericType());
        this.name = field.getName();
    }

    public JavaElementImpl(Constructor<?> constructor, int index) {
        this.anchor = constructor;
        this.elementType = ElementType.PARAMETER;
-        this.type = constructor.getParameterTypes()[index];
-        this.genericType = constructor.getGenericParameterTypes()[index];
+ this.type = new WeakReference<Class<?>>(constructor.getParameterTypes()[index]); + this.genericType = new WeakReference<Type>(constructor.getGenericParameterTypes()[index]);
        this.index = index;
        this.name = "";
    }
@@ -76,8 +77,8 @@
    public JavaElementImpl(Method method, int index) {
        this.anchor = method;
        this.elementType = ElementType.PARAMETER;
-        this.type = method.getParameterTypes()[index];
-        this.genericType = method.getGenericParameterTypes()[index];
+ this.type = new WeakReference<Class<?>>(method.getParameterTypes()[index]); + this.genericType = new WeakReference<Type>(method.getGenericParameterTypes()[index]);
        this.index = index;
        this.name = "";
    }
@@ -92,7 +93,7 @@
     */
public JavaElementImpl(String name, Class<?> type, Class<? extends Annotation> classifer) {
        super();
-        this.type = type;
+        this.type = new WeakReference<Class<?>>(type);
        this.name = name;
        this.classifer = classifer;
    }
@@ -115,7 +116,7 @@
     * @return the genericType
     */
    public Type getGenericType() {
-        return genericType;
+        return genericType.get();
    }

    /**
@@ -129,7 +130,7 @@
     * @return the type
     */
    public Class<?> getType() {
-        return type;
+        return type.get();
    }

    public Annotation[] getAnnotations() {

Modified: tuscany/branches/sca-java-1.5.2/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java URL: http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.5.2/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java?rev=828086&r1=828085&r2=828086&view=diff
==============================================================================
--- tuscany/branches/sca-java-1.5.2/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java (original) +++ tuscany/branches/sca-java-1.5.2/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java Wed Oct 21 16:27:30 2009
@@ -18,6 +18,7 @@
 */
package org.apache.tuscany.sca.interfacedef.impl;

+import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -43,8 +44,8 @@
 */
public class DataTypeImpl<L> implements DataType<L> {
    private String dataBinding;
-    private Class<?> physical;
-    private Type genericType;
+    private WeakReference<Class<?>> physical;
+    private WeakReference<Type> genericType;
    private L logical;
    private Map<Class<?>, Object> metaDataMap;

@@ -77,8 +78,8 @@
public DataTypeImpl(String dataBinding, Class<?> physical, Type genericType, L logical) {
        super();
        this.dataBinding = dataBinding;
-        this.physical = physical;
-        this.genericType = genericType;
+        this.physical = new WeakReference<Class<?>>(physical);
+        this.genericType = new WeakReference<Type>(genericType);
        this.logical = logical;
    }

@@ -88,14 +89,14 @@
     * @return the physical type used by the runtime
     */
    public Class<?> getPhysical() {
-        return physical;
+        return physical.get();
    }

    /**
     * @param physical the physical to set
     */
    public void setPhysical(Class<?> physical) {
-        this.physical = physical;
+        this.physical = new WeakReference<Class<?>>(physical);
    }

    /**
@@ -103,7 +104,7 @@
     * @return The java generic type
     */
    public Type getGenericType() {
-        return genericType;
+        return genericType.get();
    }

    /**
@@ -111,7 +112,7 @@
     * @param genericType
     */
    public void setGenericType(Type genericType) {
-        this.genericType = genericType;
+        this.genericType = new WeakReference<Type>(genericType);
    }

    /**
@@ -161,9 +162,9 @@
        final int prime = 31;
        int result = 1;
result = prime * result + ((dataBinding == null) ? 0 : dataBinding.hashCode()); - result = prime * result + ((genericType == null) ? 0 : genericType.hashCode()); + result = prime * result + ((genericType == null || genericType.get() == null) ? 0 : genericType.get().hashCode()); result = prime * result + ((logical == null) ? 0 : logical.hashCode()); - result = prime * result + ((physical == null) ? 0 : physical.hashCode()); + result = prime * result + ((physical == null || physical.get() == null) ? 0 : physical.get().hashCode());
        return result;
    }

@@ -181,20 +182,20 @@
                return false;
        } else if (!dataBinding.equals(other.dataBinding))
            return false;
-        if (genericType == null) {
+        if (genericType == null || genericType.get() == null) {
            if (other.genericType != null)
                return false;
-        } else if (!genericType.equals(other.genericType))
+        } else if (!genericType.get().equals(other.genericType.get()))
            return false;
        if (logical == null) {
            if (other.logical != null)
                return false;
        } else if (!logical.equals(other.logical))
            return false;
-        if (physical == null) {
+        if (physical == null || physical.get() == null) {
            if (other.physical != null)
                return false;
-        } else if (!physical.equals(other.physical))
+        } else if (!physical.get().equals(other.physical.get()))
            return false;
        return true;
    }
@@ -219,8 +220,8 @@
        StringBuilder b = new StringBuilder( 256 );
           b.append( "DataType[" );
b.append( "dataBinding=" + ((dataBinding==null) ? "null" : dataBinding) ); - b.append( ", genericType=" + ((genericType==null) ? "null" : genericType) ); - b.append( ", physical=" + ((physical==null) ? "null" : physical) ); + b.append( ", genericType=" + ((genericType==null || genericType.get()==null) ? "null" : genericType.get()) ); + b.append( ", physical=" + ((physical==null || physical.get()==null) ? "null" : physical.get()) ); b.append( ", logical=" + ((logical==null) ? "null" : logical) ); b.append( ", metaData size=" + ((metaDataMap==null) ? "0" : metaDataMap.size()) );
           b.append( "]" );


Reply via email to