summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jvm/clojure/lang/DynamicClassLoader.java23
-rw-r--r--src/jvm/clojure/lang/Keyword.java16
-rw-r--r--src/jvm/clojure/lang/Util.java18
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());
+ }
+ }
+}
}