diff options
-rw-r--r-- | src/jvm/clojure/lang/DynamicClassLoader.java | 23 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Keyword.java | 16 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Util.java | 18 |
3 files changed, 37 insertions, 20 deletions
diff --git a/src/jvm/clojure/lang/DynamicClassLoader.java b/src/jvm/clojure/lang/DynamicClassLoader.java index d27e9c86..8719dc18 100644 --- a/src/jvm/clojure/lang/DynamicClassLoader.java +++ b/src/jvm/clojure/lang/DynamicClassLoader.java @@ -14,17 +14,16 @@ package clojure.lang; import java.util.HashMap; import java.util.Map; -import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import java.net.URLClassLoader; import java.net.URL; -import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; public class DynamicClassLoader extends URLClassLoader{ HashMap<Integer, Object[]> constantVals = new HashMap<Integer, Object[]>(); -static ConcurrentHashMap<String, WeakReference<Class> >classCache = - new ConcurrentHashMap<String, WeakReference<Class> >(); +static ConcurrentHashMap<String, SoftReference<Class>>classCache = + new ConcurrentHashMap<String, SoftReference<Class> >(); static final URL[] EMPTY_URLS = new URL[]{}; @@ -42,24 +41,14 @@ public DynamicClassLoader(ClassLoader parent){ } public Class defineClass(String name, byte[] bytes, Object srcForm){ + Util.clearCache(rq, classCache); Class c = defineClass(name, bytes, 0, bytes.length); - classCache.put(name, new WeakReference(c,rq)); - //cleanup any dead entries - if(rq.poll() != null) - { - while(rq.poll() != null) - ; - for(Map.Entry<String,WeakReference<Class>> e : classCache.entrySet()) - { - if(e.getValue().get() == null) - classCache.remove(e.getKey(), e.getValue()); - } - } + classCache.put(name, new SoftReference(c,rq)); return c; } protected Class<?> findClass(String name) throws ClassNotFoundException{ - WeakReference<Class> cr = classCache.get(name); + SoftReference<Class> cr = classCache.get(name); if(cr != null) { Class c = cr.get(); diff --git a/src/jvm/clojure/lang/Keyword.java b/src/jvm/clojure/lang/Keyword.java index ac080923..75adcdd7 100644 --- a/src/jvm/clojure/lang/Keyword.java +++ b/src/jvm/clojure/lang/Keyword.java @@ -15,18 +15,28 @@ package clojure.lang; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.concurrent.ConcurrentHashMap; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; public final class Keyword implements IFn, Comparable, Named, Serializable { -private static ConcurrentHashMap<Symbol, Keyword> table = new ConcurrentHashMap(); +private static ConcurrentHashMap<Symbol, SoftReference<Keyword>> table = new ConcurrentHashMap(); +static final ReferenceQueue rq = new ReferenceQueue(); public final Symbol sym; final int hash; public static Keyword intern(Symbol sym){ + Util.clearCache(rq, table); Keyword k = new Keyword(sym); - Keyword existingk = table.putIfAbsent(sym, k); - return existingk == null ? k : existingk; + SoftReference<Keyword> existingRef = table.putIfAbsent(sym, new SoftReference<Keyword>(k,rq)); + if(existingRef == null) + return k; + Keyword existingk = existingRef.get(); + if(existingk != null) + return existingk; + //entry died in the interim, do over + return intern(sym); } public static Keyword intern(String ns, String name){ diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java index 0070264c..8ef2c637 100644 --- a/src/jvm/clojure/lang/Util.java +++ b/src/jvm/clojure/lang/Util.java @@ -13,6 +13,11 @@ package clojure.lang; import java.math.BigInteger; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.lang.ref.SoftReference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.Reference; public class Util{ static public boolean equiv(Object k1, Object k2){ @@ -89,4 +94,17 @@ static public ISeq ret1(ISeq ret, Object nil){ return ret; } +static public <K,V> void clearCache(ReferenceQueue rq, ConcurrentHashMap<K, SoftReference<V>> cache){ + //cleanup any dead entries + if(rq.poll() != null) + { + while(rq.poll() != null) + ; + for(Map.Entry<K, SoftReference<V>> e : cache.entrySet()) + { + if(e.getValue().get() == null) + cache.remove(e.getKey(), e.getValue()); + } + } +} } |