8022587: ClassCache is not optimal and leaks Source instances

Fri, 20 Sep 2013 12:11:08 +0200

author
hannesw
date
Fri, 20 Sep 2013 12:11:08 +0200
changeset 566
fa491b75d3e4
parent 565
195be8ca5c97
child 567
13210550765c
child 568
279f47b353f3

8022587: ClassCache is not optimal and leaks Source instances
Reviewed-by: lagergren, attila

src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Fri Sep 20 12:56:07 2013 +0530
     1.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Fri Sep 20 12:11:08 2013 +0200
     1.3 @@ -33,6 +33,7 @@
     1.4  import java.io.PrintWriter;
     1.5  import java.lang.invoke.MethodHandle;
     1.6  import java.lang.invoke.MethodHandles;
     1.7 +import java.lang.ref.ReferenceQueue;
     1.8  import java.lang.ref.SoftReference;
     1.9  import java.lang.reflect.Field;
    1.10  import java.util.Arrays;
    1.11 @@ -691,17 +692,41 @@
    1.12       * Cache for compiled script classes.
    1.13       */
    1.14      @SuppressWarnings("serial")
    1.15 -    private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
    1.16 +    private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
    1.17          private final int size;
    1.18 +        private final ReferenceQueue<Class<?>> queue;
    1.19  
    1.20          ClassCache(int size) {
    1.21              super(size, 0.75f, true);
    1.22              this.size = size;
    1.23 +            this.queue = new ReferenceQueue<>();
    1.24 +        }
    1.25 +
    1.26 +        void cache(final Source source, final Class<?> clazz) {
    1.27 +            put(source, new ClassReference(clazz, queue, source));
    1.28          }
    1.29  
    1.30          @Override
    1.31 -        protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
    1.32 -            return size() >= size;
    1.33 +        protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
    1.34 +            return size() > size;
    1.35 +        }
    1.36 +
    1.37 +        @Override
    1.38 +        public ClassReference get(Object key) {
    1.39 +            for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
    1.40 +                remove(ref.source);
    1.41 +            }
    1.42 +            return super.get(key);
    1.43 +        }
    1.44 +
    1.45 +    }
    1.46 +
    1.47 +    private static class ClassReference extends SoftReference<Class<?>> {
    1.48 +        private final Source source;
    1.49 +
    1.50 +        ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
    1.51 +            super(clazz, queue);
    1.52 +            this.source = source;
    1.53          }
    1.54      }
    1.55  
    1.56 @@ -709,22 +734,14 @@
    1.57      @Override
    1.58      public Class<?> findCachedClass(final Source source) {
    1.59          assert classCache != null : "Class cache used without being initialized";
    1.60 -        SoftReference<Class<?>> ref = classCache.get(source);
    1.61 -        if (ref != null) {
    1.62 -            final Class<?> clazz = ref.get();
    1.63 -            if (clazz == null) {
    1.64 -                classCache.remove(source);
    1.65 -            }
    1.66 -            return clazz;
    1.67 -        }
    1.68 -
    1.69 -        return null;
    1.70 +        ClassReference ref = classCache.get(source);
    1.71 +        return ref != null ? ref.get() : null;
    1.72      }
    1.73  
    1.74      @Override
    1.75      public void cacheClass(final Source source, final Class<?> clazz) {
    1.76          assert classCache != null : "Class cache used without being initialized";
    1.77 -        classCache.put(source, new SoftReference<Class<?>>(clazz));
    1.78 +        classCache.cache(source, clazz);
    1.79      }
    1.80  
    1.81      private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {

mercurial