1 /* 2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4530538 27 * @modules java.base/jdk.internal.misc 28 * java.management 29 * @summary Basic unit test of 30 * RuntimeMXBean.getObjectPendingFinalizationCount() 31 * 1. GC and runFinalization() to get the current pending number 32 * 2. Create some number of objects with reference and without ref. 33 * 3. Clear all the references 34 * 4. GC and runFinalization() and the finalizable objects should 35 * be garbage collected. 36 * @author Alexei Guibadoulline and Mandy Chung 37 */ 38 39 import java.lang.management.*; 40 41 public class Pending { 42 static final int NO_REF_COUNT = 600; 43 static final int REF_COUNT = 500; 44 static final int TOTAL_FINALIZABLE = (NO_REF_COUNT + REF_COUNT); 45 private static int finalized = 0; 46 private static MemoryMXBean mbean 47 = ManagementFactory.getMemoryMXBean(); 48 49 private static final String INDENT = " "; 50 private static void printFinalizerInstanceCount() { 51 if (!trace) return; 52 53 int count = jdk.internal.misc.VM.getFinalRefCount(); 54 System.out.println(INDENT + "Finalizable object Count = " + count); 55 56 count = jdk.internal.misc.VM.getPeakFinalRefCount(); 57 System.out.println(INDENT + "Peak Finalizable object Count = " + count); 58 } 59 60 private static boolean trace = false; 61 public static void main(String argv[]) throws Exception { 62 if (argv.length > 0 && argv[0].equals("trace")) { 63 trace = true; 64 } 65 66 try { 67 if (trace) { 68 // Turn on verbose:gc to track GC 69 mbean.setVerbose(true); 70 } 71 test(); 72 } finally { 73 if (trace) { 74 mbean.setVerbose(false); 75 } 76 } 77 System.out.println("Test passed."); 78 } 79 80 // Keep objs public so the optimizer will not remove them too early. 81 public static Object[] objs = null; 82 83 private static void test() throws Exception { 84 // Clean the memory and remove all objects that are pending 85 // finalization 86 System.gc(); 87 Snapshot snapshot = getSnapshotAfterFinalization(); 88 89 System.out.println("Number of objects pending for finalization:"); 90 System.out.println(" Before creating object: " + snapshot); 91 printFinalizerInstanceCount(); 92 93 // Create objects without saving reference. Should be removed at next GC. 94 for (int i = 0; i < NO_REF_COUNT; i++) { 95 new MyObject(); 96 } 97 98 snapshot = getSnapshot(); 99 System.out.println(" Afer creating objects with no ref: " + snapshot); 100 printFinalizerInstanceCount(); 101 102 // Create objects and save references. 103 objs = new Object[REF_COUNT]; 104 for (int i = 0; i < REF_COUNT; i++) { 105 objs[i] = new MyObject(); 106 } 107 snapshot = getSnapshot(); 108 System.out.println(" Afer creating objects with ref: " + snapshot); 109 printFinalizerInstanceCount(); 110 111 // Now check the expected count - GC and runFinalization will be 112 // invoked. 113 checkFinalizerCount(NO_REF_COUNT, 0); 114 115 // Clean the memory and remove all objects that are pending 116 // finalization again 117 objs = null; 118 snapshot = getSnapshot(); 119 System.out.println("Clear all references finalized = " + snapshot); 120 printFinalizerInstanceCount(); 121 122 checkFinalizerCount(TOTAL_FINALIZABLE, NO_REF_COUNT); 123 124 snapshot = getSnapshot(); 125 printFinalizerInstanceCount(); 126 127 // Check the mbean now 128 if (snapshot.curFinalized != TOTAL_FINALIZABLE) { 129 throw new RuntimeException("Wrong number of finalized objects " 130 + snapshot + ". Expected " 131 + TOTAL_FINALIZABLE); 132 } 133 134 if (snapshot.curPending != 0) { 135 throw new RuntimeException("Wrong number of objects pending " 136 + " end = " + snapshot); 137 } 138 139 } 140 141 private static void checkFinalizerCount(int expectedTotal, int curFinalized) 142 throws Exception { 143 int prevCount = -1; 144 Snapshot snapshot = getSnapshot(); 145 if (snapshot.curFinalized != curFinalized) { 146 throw new RuntimeException( 147 "Unexpected finalized objects: " + snapshot + 148 " but expected = " + curFinalized); 149 } 150 int MAX_GC_LOOP = 6; 151 for (int i = 1; 152 snapshot.curFinalized != expectedTotal && i <= MAX_GC_LOOP; 153 i++) { 154 System.gc(); 155 snapshot = getSnapshotAfterFinalization(); 156 157 if (snapshot.curFinalized == expectedTotal && 158 snapshot.curPending != 0) { 159 throw new RuntimeException( 160 "Unexpected current number of objects pending for " + 161 "finalization: " + snapshot + " but expected = 0"); 162 } 163 164 System.out.println(" After runFinalization " + i + ": " + snapshot); 165 printFinalizerInstanceCount(); 166 167 try { 168 Thread.sleep(1000); 169 } catch (Exception e) { 170 throw e; 171 } 172 } 173 if (snapshot.curFinalized != expectedTotal) { 174 throw new RuntimeException( 175 "Unexpected current number of objects pending for " + 176 "finalization: " + snapshot + " but expected > 0"); 177 } 178 } 179 180 private static Object lock = new Object(); 181 private static class MyObject { 182 Object[] dummy = new Object[10]; 183 public void finalize () { 184 synchronized (lock) { 185 finalized++; 186 } 187 } 188 } 189 190 static class Snapshot { 191 public int curFinalized; 192 public int curPending; 193 Snapshot(int f, int p) { 194 curFinalized = f; 195 curPending = p; 196 } 197 public String toString() { 198 return "Current finalized = " + curFinalized + 199 " Current pending = " + curPending; 200 } 201 } 202 203 private static Snapshot getSnapshot() { 204 synchronized (lock) { 205 int curCount = mbean.getObjectPendingFinalizationCount(); 206 return new Snapshot(finalized, curCount); 207 } 208 } 209 210 // Repeat getSnapshot until no pending finalization. 211 private static Snapshot getSnapshotAfterFinalization() throws Exception { 212 int loopCount = 0; 213 Snapshot snapshot = null; 214 while (loopCount < 100) { 215 Runtime.getRuntime().runFinalization(); 216 Thread.sleep(50); 217 snapshot = getSnapshot(); 218 if (snapshot.curPending == 0) { 219 return snapshot; 220 } 221 ++loopCount; 222 System.out.println("Waiting for curPending to be 0. snapshot=" + snapshot); 223 } 224 String msg = "Objects pending finalization is not 0. snapshot=%s"; 225 throw new RuntimeException(String.format(msg, snapshot)); 226 } 227 }