blob: 0fff93d5cd177cfa4aeb8595c0b3ea0d14c10fba [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-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 * @test
26 * @bug 4530538
27 * @summary Basic unit test of
28 * RuntimeMXBean.getObjectPendingFinalizationCount()
29 * 1. GC and runFinalization() to get the current pending number
30 * 2. Create some number of objects with reference and without ref.
31 * 3. Clear all the references
32 * 4. GC and runFinalization() and the finalizable objects should
33 * be garbage collected.
34 * @author Alexei Guibadoulline and Mandy Chung
35 *
36 */
37
38import java.lang.management.*;
39
40public class Pending {
41 final static int NO_REF_COUNT = 600;
42 final static int REF_COUNT = 600;
43 final static int TOTAL_FINALIZABLE = (NO_REF_COUNT + REF_COUNT);
44 private static int finalized = 0;
45 private static MemoryMXBean mbean
46 = ManagementFactory.getMemoryMXBean();
47
48 private static final String INDENT = " ";
49 private static void printFinalizerInstanceCount() {
50 if (!trace) return;
51
52 int count = sun.misc.VM.getFinalRefCount();
53 System.out.println(INDENT + "Finalizable object Count = " + count);
54
55 count = sun.misc.VM.getPeakFinalRefCount();
56 System.out.println(INDENT + "Peak Finalizable object Count = " + count);
57 }
58
59 private static boolean trace = false;
60 public static void main(String argv[]) throws Exception {
61 if (argv.length > 0 && argv[0].equals("trace")) {
62 trace = true;
63 }
64
65 // Turn on verbose:gc to track GC
66 mbean.setVerbose(true);
67
68 // Clean the memory and remove all objects that are pending
69 // finalization
70 System.gc();
71 Runtime.getRuntime().runFinalization();
72
73 // Let the finalizer to finish
74 try {
75 Thread.sleep(200);
76 } catch (Exception e) {
77 throw e;
78 }
79
80 // Create a number of new objects but no references to them
81 int startCount = mbean.getObjectPendingFinalizationCount();
82
83 System.out.println("Number of objects pending for finalization:");
84 System.out.println(" Before creating object: " + startCount +
85 " finalized = " + finalized);
86 printFinalizerInstanceCount();
87
88 for (int i = 0; i < NO_REF_COUNT; i++) {
89 new MyObject();
90 }
91
92 Snapshot snapshot = getSnapshot();
93 System.out.println(" Afer creating objects with no ref: " + snapshot);
94 printFinalizerInstanceCount();
95
96 Object[] objs = new Object[REF_COUNT];
97 for (int i = 0; i < REF_COUNT; i++) {
98 objs[i] = new MyObject();
99 }
100 snapshot = getSnapshot();
101 System.out.println(" Afer creating objects with ref: " + snapshot);
102 printFinalizerInstanceCount();
103
104 // Now check the expected count - GC and runFinalization will be
105 // invoked.
106 checkFinalizerCount(NO_REF_COUNT, 0);
107
108 // Clean the memory and remove all objects that are pending
109 // finalization again
110 objs = null;
111 snapshot = getSnapshot();
112 System.out.println("Clear all references finalized = " + snapshot);
113 printFinalizerInstanceCount();
114
115 checkFinalizerCount(TOTAL_FINALIZABLE, NO_REF_COUNT);
116
117 snapshot = getSnapshot();
118 printFinalizerInstanceCount();
119
120 // Check the mbean now
121 if (snapshot.curFinalized != TOTAL_FINALIZABLE) {
122 throw new RuntimeException("Wrong number of finalized objects "
123 + snapshot + ". Expected "
124 + TOTAL_FINALIZABLE);
125 }
126
127 if (startCount != 0 || snapshot.curPending != 0) {
128 throw new RuntimeException("Wrong number of objects pending "
129 + "finalization start = " + startCount
130 + " end = " + snapshot);
131 }
132
133 System.out.println("Test passed.");
134 }
135
136 private static void checkFinalizerCount(int expectedTotal, int curFinalized)
137 throws Exception {
138 int prevCount = -1;
139 Snapshot snapshot = getSnapshot();
140 if (snapshot.curFinalized != curFinalized) {
141 throw new RuntimeException(
142 "Unexpected finalized objects: " + snapshot +
143 " but expected = " + curFinalized);
144 }
145 int MAX_GC_LOOP = 6;
146 for (int i = 1;
147 snapshot.curFinalized != expectedTotal && i <= MAX_GC_LOOP;
148 i++) {
149 System.gc();
150
151 // Pause to give a chance to Finalizer thread to run
152 pause();
153
154 printFinalizerInstanceCount();
155 // Race condition may occur; attempt to check this
156 // a few times before throwing exception.
157 for (int j = 0; j < 5; j++) {
158 // poll for another current pending count
159 snapshot = getSnapshot();
160 if (snapshot.curFinalized == expectedTotal ||
161 snapshot.curPending != 0) {
162 break;
163 }
164 }
165 System.out.println(" After GC " + i + ": " + snapshot);
166
167 Runtime.getRuntime().runFinalization();
168
169 // Pause to give a chance to Finalizer thread to run
170 pause();
171
172 snapshot = getSnapshot();
173 if (snapshot.curFinalized == expectedTotal &&
174 snapshot.curPending != 0) {
175 throw new RuntimeException(
176 "Unexpected current number of objects pending for " +
177 "finalization: " + snapshot + " but expected = 0");
178 }
179
180 System.out.println(" After runFinalization " + i + ": " + snapshot);
181 printFinalizerInstanceCount();
182
183 try {
184 Thread.sleep(1000);
185 } catch (Exception e) {
186 throw e;
187 }
188 }
189 if (snapshot.curFinalized != expectedTotal) {
190 throw new RuntimeException(
191 "Unexpected current number of objects pending for " +
192 "finalization: " + snapshot + " but expected > 0");
193 }
194 }
195
196 private static Object lock = new Object();
197 private static class MyObject {
198 Object[] dummy = new Object[10];
199 public void finalize () {
200 synchronized (lock) {
201 finalized++;
202 }
203 }
204 }
205
206 static class Snapshot {
207 public int curFinalized;
208 public int curPending;
209 Snapshot(int f, int p) {
210 curFinalized = f;
211 curPending = p;
212 }
213 public String toString() {
214 return "Current finalized = " + curFinalized +
215 " Current pending = " + curPending;
216 }
217 }
218
219 private static Snapshot getSnapshot() {
220 synchronized (lock) {
221 int curCount = mbean.getObjectPendingFinalizationCount();
222 return new Snapshot(finalized, curCount);
223 }
224 }
225
226 private static Object pauseObj = new Object();
227 private static void pause() {
228 // Enter lock a without blocking
229 synchronized (pauseObj) {
230 try {
231 // may need to tune this timeout for different platforms
232 pauseObj.wait(20);
233 } catch (Exception e) {
234 System.err.println("Unexpected exception.");
235 e.printStackTrace(System.err);
236 }
237 }
238 }
239}