Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java
41161 views
/*1* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.tools;2526import sun.jvm.hotspot.debugger.JVMDebugger;2728import sun.jvm.hotspot.oops.*;29import sun.jvm.hotspot.utilities.SystemDictionaryHelper;3031import java.util.ArrayList;32import java.util.Collections;33import java.util.Comparator;34import java.util.HashMap;3536/*37* Iterates over the queue of object pending finalization and prints a38* summary of these objects in the form of a histogram.39*/40public class FinalizerInfo extends Tool {4142public FinalizerInfo() {43super();44}4546public FinalizerInfo(JVMDebugger d) {47super(d);48}4950@Override51public String getName() {52return "finalizerInfo";53}5455public static void main(String[] args) {56FinalizerInfo finfo = new FinalizerInfo();57finfo.execute(args);58}5960public void run() {61/*62* The implementation here has a dependency on the implementation of63* java.lang.ref.Finalizer. If the Finalizer implementation changes it's64* possible this method will require changes too. We looked into using65* ObjectReader to deserialize the objects from the target VM but as66* there aren't any public methods to traverse the queue it means using67* reflection which will also tie us to the implementation.68*69* The assumption here is that Finalizer.queue is the ReferenceQueue70* with the objects awaiting finalization. The ReferenceQueue queueLength71* is the number of objects in the queue, and 'head' is the head of the72* queue.73*/74InstanceKlass ik =75SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer");76final Oop[] queueref = new Oop[1];77ik.iterateStaticFields(new DefaultOopVisitor() {78public void doOop(OopField field, boolean isVMField) {79String name = field.getID().getName();80if (name.equals("queue")) {81queueref[0] = field.getValue(getObj());82}83}84});85Oop queue = queueref[0];8687InstanceKlass k = (InstanceKlass) queue.getKlass();8889LongField queueLengthField = (LongField) k.findField("queueLength", "J");90long queueLength = queueLengthField.getValue(queue);9192OopField headField = (OopField) k.findField("head", "Ljava/lang/ref/Reference;");93Oop head = headField.getValue(queue);9495System.out.println("Number of objects pending for finalization: " + queueLength);9697/*98* If 'head' is non-NULL then it is the head of a list of References.99* We iterate over the list (end of list is when head.next == head)100*/101if (head != null) {102k = (InstanceKlass) head.getKlass();103OopField referentField =104(OopField) k.findField("referent", "Ljava/lang/Object;");105OopField nextField =106(OopField) k.findField("next", "Ljava/lang/ref/Reference;");107108HashMap<Klass, ObjectHistogramElement> map = new HashMap<>();109for (;;) {110Oop referent = referentField.getValue(head);111112Klass klass = referent.getKlass();113if (!map.containsKey(klass)) {114map.put(klass, new ObjectHistogramElement(klass));115}116map.get(klass).updateWith(referent);117118Oop next = nextField.getValue(head);119if (next == null || next.equals(head)) break;120head = next;121}122123/*124* Sort results - decending order by total size125*/126ArrayList<ObjectHistogramElement> list = new ArrayList<>();127list.addAll(map.values());128Collections.sort(list, new Comparator<>() {129public int compare(ObjectHistogramElement o1, ObjectHistogramElement o2) {130return o1.compare(o2);131}132});133134/*135* Print summary of objects in queue136*/137System.out.println("");138System.out.println("Count" + "\t" + "Class description");139System.out.println("-------------------------------------------------------");140for (int i=0; i<list.size(); i++) {141ObjectHistogramElement e = (ObjectHistogramElement)list.get(i);142System.out.println(e.getCount() + "\t" + e.getDescription());143}144}145146}147}148149150