8085903: New fix for memory leak in ProtectionDomain cache
authormullan
Wed, 13 Jan 2016 09:39:26 -0500
changeset 34956 cfa4105ed600
parent 34951 4e8b871b54a7
child 34957 4a0926942b53
8085903: New fix for memory leak in ProtectionDomain cache Reviewed-by: xuelei, igerasim
jdk/src/java.base/share/classes/java/security/ProtectionDomain.java
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java	Wed Jan 13 14:51:40 2016 +0800
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java	Wed Jan 13 09:39:26 2016 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,12 @@
 
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
-import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import jdk.internal.misc.JavaSecurityAccess;
 import jdk.internal.misc.JavaSecurityProtectionDomainAccess;
@@ -472,11 +472,15 @@
      *
      * This class stores ProtectionDomains as weak keys in a ConcurrentHashMap
      * with additional support for checking and removing weak keys that are no
-     * longer in use.
+     * longer in use. There can be cases where the permission collection may
+     * have a chain of strong references back to the ProtectionDomain, which
+     * ordinarily would prevent the entry from being removed from the map. To
+     * address that, we wrap the permission collection in a SoftReference so
+     * that it can be reclaimed by the garbage collector due to memory demand.
      */
     private static class PDCache implements ProtectionDomainCache {
         private final ConcurrentHashMap<WeakProtectionDomainKey,
-                                        PermissionCollection>
+                                        SoftReference<PermissionCollection>>
                                         pdMap = new ConcurrentHashMap<>();
         private final ReferenceQueue<Key> queue = new ReferenceQueue<>();
 
@@ -485,15 +489,15 @@
             processQueue(queue, pdMap);
             WeakProtectionDomainKey weakPd =
                 new WeakProtectionDomainKey(pd, queue);
-            pdMap.putIfAbsent(weakPd, pc);
+            pdMap.put(weakPd, new SoftReference<>(pc));
         }
 
         @Override
         public PermissionCollection get(ProtectionDomain pd) {
             processQueue(queue, pdMap);
-            WeakProtectionDomainKey weakPd =
-                new WeakProtectionDomainKey(pd, queue);
-            return pdMap.get(weakPd);
+            WeakProtectionDomainKey weakPd = new WeakProtectionDomainKey(pd);
+            SoftReference<PermissionCollection> sr = pdMap.get(weakPd);
+            return (sr == null) ? null : sr.get();
         }
 
         /**
@@ -533,11 +537,20 @@
             this((pd == null ? NULL_KEY : pd.key), rq);
         }
 
+        WeakProtectionDomainKey(ProtectionDomain pd) {
+            this(pd == null ? NULL_KEY : pd.key);
+        }
+
         private WeakProtectionDomainKey(Key key, ReferenceQueue<Key> rq) {
             super(key, rq);
             hash = key.hashCode();
         }
 
+        private WeakProtectionDomainKey(Key key) {
+            super(key);
+            hash = key.hashCode();
+        }
+
         /**
          * Returns the identity hash code of the original referent.
          */