src/jdk/nashorn/internal/objects/Global.java
Print this page
@@ -31,10 +31,11 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
@@ -689,44 +690,60 @@
/**
* Cache for compiled script classes.
*/
@SuppressWarnings("serial")
- private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
+ private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
private final int size;
+ private final ReferenceQueue<Class<?>> queue;
ClassCache(int size) {
super(size, 0.75f, true);
this.size = size;
+ this.queue = new ReferenceQueue<>();
+ }
+
+ void cache(final Source source, final Class<?> clazz) {
+ put(source, new ClassReference(clazz, queue, source));
}
@Override
- protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
+ protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
return size() >= size;
}
+
+ @Override
+ public ClassReference get(Object key) {
+ for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
+ remove(ref.source);
+ }
+ return super.get(key);
+ }
+
+ }
+
+ private static class ClassReference extends SoftReference<Class<?>> {
+ private final Source source;
+
+ ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
+ super(clazz, queue);
+ this.source = source;
+ }
}
// Class cache management
@Override
public Class<?> findCachedClass(final Source source) {
assert classCache != null : "Class cache used without being initialized";
- SoftReference<Class<?>> ref = classCache.get(source);
- if (ref != null) {
- final Class<?> clazz = ref.get();
- if (clazz == null) {
- classCache.remove(source);
- }
- return clazz;
- }
-
- return null;
+ ClassReference ref = classCache.get(source);
+ return ref != null ? ref.get() : null;
}
@Override
public void cacheClass(final Source source, final Class<?> clazz) {
assert classCache != null : "Class cache used without being initialized";
- classCache.put(source, new SoftReference<Class<?>>(clazz));
+ classCache.cache(source, clazz);
}
private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
final T obj = map.get(key);
if (obj != null) {