and another take on GROOVY-3485. Even if the ThreadLocal remains it might be good to let the GC collect the cached value. In an environment with a thread pool it may otherwise happen that this is never collected.
git-svn-id: http://svn.codehaus.org/groovy/branches/GROOVY_1_6_X@16105 a5544e8c-8a19-0410-ba12-f9af4593a198
diff --git a/src/main/org/codehaus/groovy/reflection/ClassInfo.java b/src/main/org/codehaus/groovy/reflection/ClassInfo.java
index e3a6b2e..9ac0030 100644
--- a/src/main/org/codehaus/groovy/reflection/ClassInfo.java
+++ b/src/main/org/codehaus/groovy/reflection/ClassInfo.java
@@ -20,6 +20,7 @@
import org.codehaus.groovy.util.*;
import java.lang.ref.PhantomReference;
+import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -93,7 +94,11 @@
public static ClassInfo getClassInfo (Class cls) {
ThreadLocalMapHandler handler = localMapRef.get();
- if (handler!=null) return handler.get().get(cls);
+ SoftReference<LocalMap> ref=null;
+ if (handler!=null) ref = handler.get();
+ LocalMap map=null;
+ if (ref!=null) map = ref.get();
+ if (map!=null) return map.get(cls);
return (ClassInfo) globalClassSet.getOrPut(cls,null);
}
@@ -365,25 +370,27 @@
}
}
- private static class ThreadLocalMapHandler extends ThreadLocal<LocalMap> {
- LocalMap recentThreadMap;
+ private static class ThreadLocalMapHandler extends ThreadLocal<SoftReference<LocalMap>> {
+ SoftReference<LocalMap> recentThreadMapRef;
- protected LocalMap initialValue() {
- return new LocalMap();
+ protected SoftReference<LocalMap> initialValue() {
+ return new SoftReference(new LocalMap(),null);
}
- public LocalMap get() {
- LocalMap recent = recentThreadMap;
+ public SoftReference<LocalMap> get() {
+ SoftReference<LocalMap> mapRef = recentThreadMapRef;
+ LocalMap recent = null;
+ if (mapRef!=null) recent = mapRef.get();
// we don't need to handle myThread.get()==null, because in that
// case the thread has been collected, meaning the entry for the
// thread is invalid anyway, so it is valid if recent has a
// different value.
- if (recent != null && recent.myThread.get() == Thread.currentThread())
- return recent;
- else {
- final LocalMap res = super.get();
- recentThreadMap = res;
- return res;
+ if (recent != null && recent.myThread.get() == Thread.currentThread()) {
+ return mapRef;
+ } else {
+ SoftReference<LocalMap> ref = super.get();
+ recentThreadMapRef = ref;
+ return ref;
}
}
}