aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authoradinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2010-03-09 16:56:02 +0000
committeradinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2010-03-09 16:56:02 +0000
commit702704c3d5ad074271f7decf535205a360722ddf (patch)
treee31c3dff2420e992e0c6d78f59a9192feaa15f57 /src/main
parent8828594b4d4f3df5d14a5506fd74b6a1bec8ed2d (diff)
downloadjavassist-702704c3d5ad074271f7decf535205a360722ddf.tar.gz
javassist-702704c3d5ad074271f7decf535205a360722ddf.zip
fixed potential strong cyclic reference from proxy cache entries back to their class loader -- fixes JASSIST-104
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@517 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java133
1 files changed, 76 insertions, 57 deletions
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java
index c6cbb1f5..6f0a1c46 100644
--- a/src/main/javassist/util/proxy/ProxyFactory.java
+++ b/src/main/javassist/util/proxy/ProxyFactory.java
@@ -22,11 +22,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
-import java.util.HashMap;
-import java.util.WeakHashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.lang.ref.WeakReference;
import javassist.CannotCompileException;
@@ -174,33 +170,70 @@ public class ProxyFactory {
private static WeakHashMap proxyCache = new WeakHashMap();
- static class CacheKey {
- String classes;
+ /**
+ * store details of a specific proxy created using a given method filter and handler
+ */
+ static class ProxyDetails {
MethodFilter filter;
- private int hash;
- WeakReference proxyClass;
MethodHandler handler;
+ Class proxyClass;
- public CacheKey(Class superClass, Class[] interfaces,
- MethodFilter f, MethodHandler h)
+ ProxyDetails(MethodFilter filter, MethodHandler handler, Class proxyClass)
{
- classes = getKey(superClass, interfaces);
- hash = classes.hashCode();
- filter = f;
- handler = h;
- proxyClass = null;
+ this.filter = filter;
+ this.handler = handler;
+ this.proxyClass = proxyClass;
}
+ }
- public int hashCode() { return hash; }
+ /**
+ * collect together details of all proxies associated with a given classloader which are constructed
+ * from a given superclass and set of interfaces
+ */
+ static class ProxySet {
+ String classes; // key constructed from super/interfaces names
+ List proxyDetails; // hold details of all proxies with given super/interfaces
- public boolean equals(Object obj) {
- if (obj instanceof CacheKey) {
- CacheKey target = (CacheKey)obj;
- return target.filter == filter && target.handler == handler
- && target.classes.equals(classes);
+ public ProxySet(String key)
+ {
+ classes = key;
+ proxyDetails = new ArrayList();
+ }
+
+ /**
+ * retrieve an entry from the set with the given filter and handler
+ * @param filter
+ * @param handler
+ * @return the proxy details or null if it is not found
+ */
+ public ProxyDetails lookup(MethodFilter filter, MethodHandler handler)
+ {
+ Iterator iterator = proxyDetails.iterator();
+ while (iterator.hasNext()) {
+ ProxyDetails details = (ProxyDetails)iterator.next();
+ if (details.filter == filter && details.handler == handler) {
+ return details;
+ }
}
- else
- return false;
+ return null;
+ }
+
+ /**
+ * add details of a new proxy to the set
+ * @param details must not contain the same filter and handler as any existing entry in the set
+ */
+ public void add(ProxyDetails details)
+ {
+ proxyDetails.add(details);
+ }
+
+ /**
+ * remove details of an existing proxy from the set
+ * @param details must be in the set
+ */
+ public void remove(ProxyDetails details)
+ {
+ proxyDetails.remove(details);
}
static String getKey(Class superClass, Class[] interfaces) {
@@ -283,7 +316,9 @@ public class ProxyFactory {
}
private void createClass2(ClassLoader cl) {
- CacheKey key = new CacheKey(superClass, interfaces, methodFilter, handler);
+ String key = ProxySet.getKey(superClass, interfaces);
+ WeakReference reference;
+ ProxySet set;
/*
* Excessive concurrency causes a large memory footprint and slows the
* execution speed down (with JDK 1.5). Thus, we use a jumbo lock for
@@ -294,45 +329,29 @@ public class ProxyFactory {
if (cacheForTheLoader == null) {
cacheForTheLoader = new HashMap();
proxyCache.put(cl, cacheForTheLoader);
- cacheForTheLoader.put(key, key);
}
- else {
- CacheKey found = (CacheKey)cacheForTheLoader.get(key);
- if (found == null)
- cacheForTheLoader.put(key, key);
- else {
- key = found;
- Class c = isValidEntry(key); // no need to synchronize
- if (c != null) {
- thisClass = c;
- return;
- }
- }
+ reference = (WeakReference)cacheForTheLoader.get(key);
+ if (reference != null) {
+ set = (ProxySet)reference.get();
+ } else {
+ set = null;
}
- // }
-
- // synchronized (key) {
- Class c = isValidEntry(key);
- if (c == null) {
+ if (set == null) {
+ set = new ProxySet(key);
+ reference = new WeakReference(set);
+ cacheForTheLoader.put(key, reference);
+ }
+ ProxyDetails details = set.lookup(methodFilter, handler);
+ if (details == null) {
createClass3(cl);
- key.proxyClass = new WeakReference(thisClass);
+ details = new ProxyDetails(methodFilter, handler, thisClass);
+ set.add(details);
+ } else {
+ thisClass = details.proxyClass;
}
- else
- thisClass = c;
// }
}
- private Class isValidEntry(CacheKey key) {
- WeakReference ref = key.proxyClass;
- if (ref != null) {
- Class c = (Class)ref.get();
- if(c != null)
- return c;
- }
-
- return null;
- }
-
private void createClass3(ClassLoader cl) {
try {
ClassFile cf = make();