0
|
1 /*
|
|
2 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 *
|
|
5 * This code is free software; you can redistribute it and/or modify it
|
|
6 * under the terms of the GNU General Public License version 2 only, as
|
|
7 * published by the Free Software Foundation.
|
|
8 *
|
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 * version 2 for more details (a copy is included in the LICENSE file that
|
|
13 * accompanied this code).
|
|
14 *
|
|
15 * You should have received a copy of the GNU General Public License version
|
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 *
|
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.tools;
|
|
26
|
|
27 import sun.jvm.hotspot.tools.*;
|
|
28
|
|
29 import sun.jvm.hotspot.oops.*;
|
|
30 import sun.jvm.hotspot.runtime.VM;
|
|
31 import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
|
|
32 import sun.jvm.hotspot.utilities.ObjectReader;
|
|
33 import sun.jvm.hotspot.utilities.MarkBits;
|
|
34
|
|
35 import java.util.HashMap;
|
|
36 import java.util.ArrayList;
|
|
37 import java.util.Collections;
|
|
38 import java.util.Comparator;
|
|
39
|
|
40 /*
|
|
41 * Iterates over the queue of object pending finalization and prints a
|
|
42 * summary of these objects in the form of a histogram.
|
|
43 */
|
|
44 public class FinalizerInfo extends Tool {
|
|
45 public static void main(String[] args) {
|
|
46 FinalizerInfo finfo = new FinalizerInfo();
|
|
47 finfo.start(args);
|
|
48 finfo.stop();
|
|
49 }
|
|
50
|
|
51 public void run() {
|
|
52 /*
|
|
53 * The implementation here has a dependency on the implementation of
|
|
54 * java.lang.ref.Finalizer. If the Finalizer implementation changes it's
|
|
55 * possible this method will require changes too. We looked into using
|
|
56 * ObjectReader to deserialize the objects from the target VM but as
|
|
57 * there aren't any public methods to traverse the queue it means using
|
|
58 * reflection which will also tie us to the implementation.
|
|
59 *
|
|
60 * The assumption here is that Finalizer.queue is the ReferenceQueue
|
|
61 * with the objects awaiting finalization. The ReferenceQueue queueLength
|
|
62 * is the number of objects in the queue, and 'head' is the head of the
|
|
63 * queue.
|
|
64 */
|
|
65 InstanceKlass ik =
|
|
66 SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer");
|
|
67 final OopField queueField[] = new OopField[1];
|
|
68 ik.iterateFields(new DefaultOopVisitor() {
|
|
69 public void doOop(OopField field, boolean isVMField) {
|
|
70 String name = field.getID().getName();
|
|
71 if (name.equals("queue")) {
|
|
72 queueField[0] = field;
|
|
73 }
|
|
74 }
|
|
75 }, false);
|
|
76 Oop queue = queueField[0].getValue(ik);
|
|
77
|
|
78 InstanceKlass k = (InstanceKlass) queue.getKlass();
|
|
79
|
|
80 LongField queueLengthField = (LongField) k.findField("queueLength", "J");
|
|
81 long queueLength = queueLengthField.getValue(queue);
|
|
82
|
|
83 OopField headField = (OopField) k.findField("head", "Ljava/lang/ref/Reference;");
|
|
84 Oop head = headField.getValue(queue);
|
|
85
|
|
86 System.out.println("Number of objects pending for finalization: " + queueLength);
|
|
87
|
|
88 /*
|
|
89 * If 'head' is non-NULL then it is the head of a list of References.
|
|
90 * We iterate over the list (end of list is when head.next == head)
|
|
91 */
|
|
92 if (head != null) {
|
|
93 k = (InstanceKlass) head.getKlass();
|
|
94 OopField referentField =
|
|
95 (OopField) k.findField("referent", "Ljava/lang/Object;");
|
|
96 OopField nextField =
|
|
97 (OopField) k.findField("next", "Ljava/lang/ref/Reference;");
|
|
98
|
|
99 HashMap map = new HashMap();
|
|
100 for (;;) {
|
|
101 Oop referent = referentField.getValue(head);
|
|
102
|
|
103 Klass klass = referent.getKlass();
|
|
104 if (!map.containsKey(klass)) {
|
|
105 map.put(klass, new ObjectHistogramElement(klass));
|
|
106 }
|
|
107 ((ObjectHistogramElement)map.get(klass)).updateWith(referent);
|
|
108
|
|
109 Oop next = nextField.getValue(head);
|
|
110 if (next == null || next.equals(head)) break;
|
|
111 head = next;
|
|
112 }
|
|
113
|
|
114 /*
|
|
115 * Sort results - decending order by total size
|
|
116 */
|
|
117 ArrayList list = new ArrayList();
|
|
118 list.addAll(map.values());
|
|
119 Collections.sort(list, new Comparator() {
|
|
120 public int compare(Object o1, Object o2) {
|
|
121 return ((ObjectHistogramElement)o1).compare((ObjectHistogramElement)o2);
|
|
122 }
|
|
123 });
|
|
124
|
|
125 /*
|
|
126 * Print summary of objects in queue
|
|
127 */
|
|
128 System.out.println("");
|
|
129 System.out.println("Count" + "\t" + "Class description");
|
|
130 System.out.println("-------------------------------------------------------");
|
|
131 for (int i=0; i<list.size(); i++) {
|
|
132 ObjectHistogramElement e = (ObjectHistogramElement)list.get(i);
|
|
133 System.out.println(e.getCount() + "\t" + e.getDescription());
|
|
134 }
|
|
135 }
|
|
136
|
|
137 }
|
|
138 }
|