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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1997, 2013, 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 --- 1,7 ---- /* ! * 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,39 **** --- 30,44 ---- 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,226 **** --- 222,275 ---- } } } } + // 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 instanceCount; + private final String className; + + int getInstanceCount() { return instanceCount; } + + FinalizerHistogramEntry(Map.Entry<String, int[]> e) { + className = e.getKey(); + instanceCount = 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.getInstanceCount(), e1.getInstanceCount())); + return fhe; + } + + static { ThreadGroup tg = Thread.currentThread().getThreadGroup(); for (ThreadGroup tgn = tg; tgn != null; tg = tgn, tgn = tg.getParent());