10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.ref; 27 28 import java.security.PrivilegedAction; 29 import java.security.AccessController; 30 import sun.misc.JavaLangAccess; 31 import sun.misc.ManagedLocalsThread; 32 import sun.misc.SharedSecrets; 33 import sun.misc.VM; 34 35 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in 36 same package as the Reference 37 class */ 38 39 private static ReferenceQueue<Object> queue = new ReferenceQueue<>(); 40 private static Finalizer unfinalized = null; 41 private static final Object lock = new Object(); 42 43 private Finalizer 44 next = null, 45 prev = null; 46 47 private boolean hasBeenFinalized() { 48 return (next == this); 49 } 167 return; 168 } 169 170 forkSecondaryFinalizer(new Runnable() { 171 private volatile boolean running; 172 public void run() { 173 // in case of recursive call to run() 174 if (running) 175 return; 176 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 177 running = true; 178 for (;;) { 179 Finalizer f; 180 synchronized (lock) { 181 f = unfinalized; 182 if (f == null) break; 183 unfinalized = f.next; 184 } 185 f.runFinalizer(jla); 186 }}}); 187 } 188 189 private static class FinalizerThread extends ManagedLocalsThread { 190 private volatile boolean running; 191 FinalizerThread(ThreadGroup g) { 192 super(g, "Finalizer"); 193 } 194 public void run() { 195 // in case of recursive call to run() 196 if (running) 197 return; 198 199 // Finalizer thread starts before System.initializeSystemClass 200 // is called. Wait until JavaLangAccess is available 201 while (!VM.isBooted()) { 202 // delay until VM completes initialization 203 try { 204 VM.awaitBooted(); 205 } catch (InterruptedException x) { 206 // ignore and continue | 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.ref; 27 28 import java.security.PrivilegedAction; 29 import java.security.AccessController; 30 import java.util.Arrays; 31 import java.util.HashMap; 32 import java.util.Map; 33 34 import sun.misc.JavaLangAccess; 35 import sun.misc.ManagedLocalsThread; 36 import sun.misc.SharedSecrets; 37 import sun.misc.VM; 38 39 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in 40 same package as the Reference 41 class */ 42 43 private static ReferenceQueue<Object> queue = new ReferenceQueue<>(); 44 private static Finalizer unfinalized = null; 45 private static final Object lock = new Object(); 46 47 private Finalizer 48 next = null, 49 prev = null; 50 51 private boolean hasBeenFinalized() { 52 return (next == this); 53 } 171 return; 172 } 173 174 forkSecondaryFinalizer(new Runnable() { 175 private volatile boolean running; 176 public void run() { 177 // in case of recursive call to run() 178 if (running) 179 return; 180 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 181 running = true; 182 for (;;) { 183 Finalizer f; 184 synchronized (lock) { 185 f = unfinalized; 186 if (f == null) break; 187 unfinalized = f.next; 188 } 189 f.runFinalizer(jla); 190 }}}); 191 } 192 193 static String printFinalizationQueue() { 194 Map<String, int[]> countMap = new HashMap<>(); 195 queue.forEach(r -> { 196 Object referent = r.get(); 197 if (referent != null) { 198 countMap.computeIfAbsent( 199 referent.getClass().getName(), k -> new int[1])[0]++; 200 /* Clear stack slot containing this variable, to decrease 201 the chances of false retention with a conservative GC */ 202 referent = null; 203 } 204 }); 205 @SuppressWarnings("unchecked") 206 Map.Entry<String, int[]>[] entries = countMap.entrySet().toArray( 207 new Map.Entry[countMap.size()] 208 ); 209 Arrays.sort(entries, (e1, e2) -> 210 Integer.compare(e2.getValue()[0], e1.getValue()[0])); 211 StringBuilder sb = new StringBuilder(); 212 for (Map.Entry<String, int[]> e : entries) { 213 sb.append("Class: ").append(e.getKey()) 214 .append(" count: ").append(e.getValue()[0]).append("\n"); 215 } 216 return sb.toString(); 217 } 218 219 private static class FinalizerThread extends ManagedLocalsThread { 220 private volatile boolean running; 221 FinalizerThread(ThreadGroup g) { 222 super(g, "Finalizer"); 223 } 224 public void run() { 225 // in case of recursive call to run() 226 if (running) 227 return; 228 229 // Finalizer thread starts before System.initializeSystemClass 230 // is called. Wait until JavaLangAccess is available 231 while (!VM.isBooted()) { 232 // delay until VM completes initialization 233 try { 234 VM.awaitBooted(); 235 } catch (InterruptedException x) { 236 // ignore and continue |