diff agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.tools;
+
+import sun.jvm.hotspot.tools.*;
+
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
+import sun.jvm.hotspot.utilities.ObjectReader;
+import sun.jvm.hotspot.utilities.MarkBits;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/*
+ * Iterates over the queue of object pending finalization and prints a
+ * summary of these objects in the form of a histogram.
+ */
+public class FinalizerInfo extends Tool {
+    public static void main(String[] args) {
+        FinalizerInfo finfo = new FinalizerInfo();
+        finfo.start(args);
+        finfo.stop();
+    }
+
+    public void run() {
+        /*
+         * The implementation here has a dependency on the implementation of
+         * java.lang.ref.Finalizer. If the Finalizer implementation changes it's
+         * possible this method will require changes too. We looked into using
+         * ObjectReader to deserialize the objects from the target VM but as
+         * there aren't any public methods to traverse the queue it means using
+         * reflection which will also tie us to the implementation.
+         *
+         * The assumption here is that Finalizer.queue is the ReferenceQueue
+         * with the objects awaiting finalization. The ReferenceQueue queueLength
+         * is the number of objects in the queue, and 'head' is the head of the
+         * queue.
+         */
+        InstanceKlass ik =
+            SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer");
+        final OopField queueField[] = new OopField[1];
+        ik.iterateFields(new DefaultOopVisitor() {
+            public void doOop(OopField field, boolean isVMField) {
+                String name = field.getID().getName();
+                if (name.equals("queue")) {
+                    queueField[0] = field;
+                }
+            }
+        }, false);
+        Oop queue = queueField[0].getValue(ik);
+
+        InstanceKlass k = (InstanceKlass) queue.getKlass();
+
+        LongField queueLengthField = (LongField) k.findField("queueLength", "J");
+        long queueLength = queueLengthField.getValue(queue);
+
+        OopField headField =  (OopField) k.findField("head", "Ljava/lang/ref/Reference;");
+        Oop head = headField.getValue(queue);
+
+        System.out.println("Number of objects pending for finalization: " + queueLength);
+
+        /*
+         * If 'head' is non-NULL then it is the head of a list of References.
+         * We iterate over the list (end of list is when head.next == head)
+         */
+        if (head != null) {
+            k = (InstanceKlass) head.getKlass();
+            OopField referentField =
+                (OopField) k.findField("referent", "Ljava/lang/Object;");
+            OopField nextField =
+                (OopField) k.findField("next", "Ljava/lang/ref/Reference;");
+
+            HashMap map = new HashMap();
+            for (;;) {
+                Oop referent = referentField.getValue(head);
+
+                Klass klass = referent.getKlass();
+                if (!map.containsKey(klass)) {
+                    map.put(klass, new ObjectHistogramElement(klass));
+                }
+                ((ObjectHistogramElement)map.get(klass)).updateWith(referent);
+
+                Oop next = nextField.getValue(head);
+                if (next == null || next.equals(head)) break;
+                head = next;
+            }
+
+            /*
+             * Sort results - decending order by total size
+             */
+            ArrayList list = new ArrayList();
+            list.addAll(map.values());
+            Collections.sort(list, new Comparator() {
+              public int compare(Object o1, Object o2) {
+                  return ((ObjectHistogramElement)o1).compare((ObjectHistogramElement)o2);
+              }
+            });
+
+            /*
+             * Print summary of objects in queue
+             */
+            System.out.println("");
+            System.out.println("Count" + "\t" + "Class description");
+            System.out.println("-------------------------------------------------------");
+            for (int i=0; i<list.size(); i++) {
+                ObjectHistogramElement e = (ObjectHistogramElement)list.get(i);
+                System.out.println(e.getCount() + "\t" + e.getDescription());
+            }
+       }
+
+   }
+}