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 4892507 8020875 8021335 27 * @summary Basic Test for the following reset methods: 28 * - ThreadMXBean.resetPeakThreadCount() 29 * @author Mandy Chung 30 * @author Jaroslav Bachorik 31 * 32 * @build ResetPeakThreadCount 33 * @build ThreadDump 34 * @run main/othervm ResetPeakThreadCount 35 */ 36 37 import java.lang.management.*; 38 39 public class ResetPeakThreadCount { 40 // initial number of new threads started 41 private static final int DAEMON_THREADS_1 = 8; 42 private static final int EXPECTED_PEAK_DELTA_1 = 8; 43 44 // Terminate half of the threads started 45 private static final int TERMINATE_1 = 4; 46 47 // start new threads but expected the peak unchanged 48 private static final int DAEMON_THREADS_2 = 2; 49 private static final int EXPECTED_PEAK_DELTA_2 = 0; 50 51 // peak thread count reset before starting new threads 52 private static final int DAEMON_THREADS_3 = 4; 53 private static final int EXPECTED_PEAK_DELTA_3 = 4; 54 55 private static final int TERMINATE_2 = 8; 56 57 private static final int TERMINATE_3 = 2; 58 59 private static final int ALL_THREADS = DAEMON_THREADS_1 + 60 DAEMON_THREADS_2 + DAEMON_THREADS_3; 61 // barrier for threads communication 62 private static final Barrier barrier = new Barrier(DAEMON_THREADS_1); 63 64 private static final Thread allThreads[] = new Thread[ALL_THREADS]; 65 private static final boolean live[] = new boolean[ALL_THREADS]; 66 private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); 67 private static volatile boolean testFailed = false; 68 69 public static void main(String[] argv) throws Exception { 70 // This test does not expect any threads to be created 71 // by the test harness after main() is invoked. 72 // The checkThreadCount() method is to produce more 73 // diagnostic information in case any unexpected test failure occur. 74 long previous = mbean.getThreadCount(); 75 long current = previous; 76 77 // reset the peak to start from a scratch 78 resetPeak(current); 79 80 // start DAEMON_THREADS_1 number of threads 81 current = startThreads(0, DAEMON_THREADS_1, EXPECTED_PEAK_DELTA_1); 82 83 checkThreadCount(previous, current, DAEMON_THREADS_1); 84 previous = current; 85 86 // terminate TERMINATE_1 number of threads and reset peak 87 current = terminateThreads(0, TERMINATE_1); 88 89 checkThreadCount(previous, current, TERMINATE_1 * -1); 90 91 previous = current; 92 93 // start DAEMON_THREADS_2 number of threads 94 // expected peak is unchanged 95 current = startThreads(DAEMON_THREADS_1, DAEMON_THREADS_2, 96 EXPECTED_PEAK_DELTA_2); 97 98 checkThreadCount(previous, current, DAEMON_THREADS_2); 99 previous = current; 100 101 // Reset the peak 102 resetPeak(current); 103 104 // start DAEMON_THREADS_3 number of threads 105 current = startThreads(DAEMON_THREADS_1 + DAEMON_THREADS_2, 106 DAEMON_THREADS_3, EXPECTED_PEAK_DELTA_3); 107 108 checkThreadCount(previous, current, DAEMON_THREADS_3); 109 previous = current; 110 111 // terminate TERMINATE_2 number of threads and reset peak 112 current = terminateThreads(TERMINATE_1, TERMINATE_2); 113 114 checkThreadCount(previous, current, TERMINATE_2 * -1); 115 previous = current; 116 117 resetPeak(current); 118 119 // terminate TERMINATE_3 number of threads and reset peak 120 current = terminateThreads(TERMINATE_1 + TERMINATE_2, TERMINATE_3); 121 122 checkThreadCount(previous, current, TERMINATE_3 * -1); 123 resetPeak(current); 124 125 if (testFailed) 126 throw new RuntimeException("TEST FAILED."); 127 128 System.out.println("Test passed"); 129 } 130 131 private static long startThreads(int from, int count, int delta) throws InterruptedException { 132 // get current peak thread count 133 long peak1 = mbean.getPeakThreadCount(); 134 long current = mbean.getThreadCount(); 135 136 // Start threads and wait to be sure they all are alive 137 System.out.println("Starting " + count + " threads...."); 138 barrier.set(count); 139 synchronized(live) { 140 for (int i = from; i < (from + count); i++) { 141 live[i] = true; 142 allThreads[i] = new MyThread(i); 143 allThreads[i].setDaemon(true); 144 allThreads[i].start(); 145 } 146 } 147 // wait until all threads have started. 148 barrier.await(); 149 150 // get peak thread count after daemon threads have started 151 long peak2 = mbean.getPeakThreadCount(); 152 153 System.out.println(" Current = " + mbean.getThreadCount() + 154 " Peak before = " + peak1 + " after: " + peak2); 155 156 if (peak2 != (peak1 + delta)) { 157 throw new RuntimeException("Current Peak = " + peak2 + 158 " Expected to be == previous peak = " + peak1 + " + " + 159 delta); 160 } 161 current = mbean.getThreadCount(); 162 System.out.println(" Live thread count before returns " + current); 163 return current; 164 } 165 166 private static long terminateThreads(int from, int count) throws InterruptedException { 167 // get current peak thread count 168 long peak1 = mbean.getPeakThreadCount(); 169 170 // Stop daemon threads and wait to be sure they all are dead 171 System.out.println("Terminating " + count + " threads...."); 172 barrier.set(count); 173 synchronized(live) { 174 for (int i = from; i < (from+count); i++) { 175 live[i] = false; 176 } 177 live.notifyAll(); 178 } 179 // wait until daemon threads terminated. 180 barrier.await(); 181 182 // get peak thread count after daemon threads have terminated 183 long peak2 = mbean.getPeakThreadCount(); 184 // assuming no system thread is added 185 if (peak2 != peak1) { 186 throw new RuntimeException("Current Peak = " + peak2 + 187 " Expected to be = previous peak = " + peak1); 188 } 189 190 for (int i = from; i < (from+count); i++) { 191 allThreads[i].join(); 192 } 193 194 long current = mbean.getThreadCount(); 195 System.out.println(" Live thread count before returns " + current); 196 return current; 197 } 198 199 private static void resetPeak(long expectedCount) { 200 long peak3 = mbean.getPeakThreadCount(); 201 long current = mbean.getThreadCount(); 202 203 // Nightly testing showed some intermittent failure. 204 // Check here to get diagnostic information if some strange 205 // behavior occurs. 206 checkThreadCount(expectedCount, current, 0); 207 208 // Reset peak thread count 209 mbean.resetPeakThreadCount(); 210 211 long afterResetPeak = mbean.getPeakThreadCount(); 212 long afterResetCurrent = mbean.getThreadCount(); 213 System.out.println("Reset peak before = " + peak3 + 214 " current = " + current + 215 " after reset peak = " + afterResetPeak + 216 " current = " + afterResetCurrent); 217 218 if (afterResetPeak != current) { 219 throw new RuntimeException("Current Peak after reset = " + 220 afterResetPeak + 221 " Expected to be = current count = " + current); 222 } 223 } 224 225 private static void checkThreadCount(long previous, long current, int expectedDelta) { 226 if (current != previous + expectedDelta) { 227 ThreadDump.threadDump(); 228 throw new RuntimeException("***** Unexpected thread count:" + 229 " previous = " + previous + 230 " current = " + current + 231 " delta = " + expectedDelta + "*****"); 232 } 233 } 234 235 // The MyThread thread lives as long as correspondent live[i] value is true 236 private static class MyThread extends Thread { 237 int id; 238 239 MyThread(int id) { 240 this.id = id; 241 } 242 243 public void run() { 244 // signal started 245 barrier.signal(); 246 synchronized(live) { 247 while (live[id]) { 248 try { 249 live.wait(100); 250 } catch (InterruptedException e) { 251 System.out.println("Unexpected exception is thrown."); 252 e.printStackTrace(System.out); 253 testFailed = true; 254 } 255 } 256 } 257 // signal about to exit 258 barrier.signal(); 259 } 260 } 261 262 }