src/java.base/share/classes/java/lang/ref/Finalizer.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -30,10 +30,15 @@
 import sun.misc.JavaLangAccess;
 import sun.misc.ManagedLocalsThread;
 import sun.misc.SharedSecrets;
 import sun.misc.VM;
 
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Arrays;
+
 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
                                                           same package as the Reference
                                                           class */
 
     private static ReferenceQueue<Object> queue = new ReferenceQueue<>();

@@ -217,10 +222,54 @@
                 }
             }
         }
     }
 
+    // Support for GC.finalizer_info DCMD
+
+    // Fileds of the class below is accessed directly by VM
+    // using hardcoded field offsets, so don't change
+    // class layout.
+    static class FinalizerHistogramEntry {
+        private final int count;
+        private final String name;
+
+        int getCount() { return count; }
+
+        FinalizerHistogramEntry(Map.Entry<String, int[]> e) {
+            name = e.getKey();
+            count =  e.getValue()[0];
+        }
+    };
+
+    // This method called by VM from FinalizerInfoDCmd and
+    @SuppressWarnings({"unchecked","rawtypes"})
+    static Object[] getFinalizerHistogram() {
+        Map<String, int[]> countMap = new HashMap<>();
+        queue.forEach(r -> {
+            Object referent = r.get();
+            if (referent != null) {
+                countMap.computeIfAbsent(
+                    referent.getClass().getName(), k -> new int[1])[0]++;
+                /* Clear stack slot containing this variable, to decrease
+                   the chances of false retention with a conservative GC */
+                referent = null;
+              }
+        });
+
+        // Copy HashMap entry set to array of objects accessible from VM
+        FinalizerHistogramEntry fhe[] = new FinalizerHistogramEntry[countMap.size()];
+        int i = 0;
+        for (Map.Entry<String, int[]> e : countMap.entrySet()) {
+             fhe[i++] = new  FinalizerHistogramEntry(e);
+        }
+
+        Arrays.sort(fhe, (e1, e2) -> Integer.compare(e2.getCount(), e1.getCount()));
+        return fhe;
+    }
+
+
     static {
         ThreadGroup tg = Thread.currentThread().getThreadGroup();
         for (ThreadGroup tgn = tg;
              tgn != null;
              tg = tgn, tgn = tg.getParent());