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 * @summary Basic unit test of ThreadMXBean.getAllThreadIds() 28 * @author Alexei Guibadoulline and Mandy Chung 29 * 30 * @run main/othervm AllThreadIds 31 */ 32 33 import java.lang.management.*; 34 import java.util.concurrent.Phaser; 35 36 public class AllThreadIds { 37 final static int DAEMON_THREADS = 20; 38 final static int USER_THREADS = 5; 39 final static int ALL_THREADS = DAEMON_THREADS + USER_THREADS; 40 private static final boolean live[] = new boolean[ALL_THREADS]; 41 private static final Thread allThreads[] = new Thread[ALL_THREADS]; 42 private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); 43 private static boolean testFailed = false; 44 private static boolean trace = false; 45 46 private static long prevTotalThreadCount = 0; 47 private static int prevLiveThreadCount = 0; 48 private static int prevPeakThreadCount = 0; 49 private static long curTotalThreadCount = 0; 50 private static int curLiveThreadCount = 0; 51 private static int curPeakThreadCount = 0; 52 53 private static final Phaser startupCheck = new Phaser(ALL_THREADS + 1); 54 55 private static void printThreadList() { 56 if (!trace) return; 57 58 long[] list = mbean.getAllThreadIds(); 59 for (int i = 1; i <= list.length; i++) { 60 System.out.println(i + ": Thread id = " + list[i-1]); 61 } 62 for (int i = 0; i < ALL_THREADS; i++) { 63 Thread t = allThreads[i]; 64 System.out.println(t.getName() + " Id = " + t.getId() + 65 " die = " + live[i] + 66 " alive = " + t.isAlive()); 67 } 68 } 69 70 private static void fail(String msg) { 71 trace = true; 72 printThreadList(); 73 throw new RuntimeException(msg); 74 } 75 76 private static void checkThreadCount(int numNewThreads, 77 int numTerminatedThreads) 78 throws Exception { 79 prevTotalThreadCount = curTotalThreadCount; 80 prevLiveThreadCount = curLiveThreadCount; 81 prevPeakThreadCount = curPeakThreadCount; 82 curTotalThreadCount = mbean.getTotalStartedThreadCount(); 83 curLiveThreadCount = mbean.getThreadCount(); 84 curPeakThreadCount = mbean.getPeakThreadCount(); 85 86 if ((curLiveThreadCount - prevLiveThreadCount) != 87 (numNewThreads - numTerminatedThreads)) { 88 fail("Unexpected number of live threads: " + 89 " Prev live = " + prevLiveThreadCount + 90 " Current live = " + curLiveThreadCount + 91 " Threads added = " + numNewThreads + 92 " Threads terminated = " + numTerminatedThreads); 93 } 94 if (curPeakThreadCount - prevPeakThreadCount != numNewThreads) { 95 fail("Unexpected number of peak threads: " + 96 " Prev peak = " + prevPeakThreadCount + 97 " Current peak = " + curPeakThreadCount + 98 " Threads added = " + numNewThreads); 99 } 100 if (curTotalThreadCount - prevTotalThreadCount != numNewThreads) { 101 fail("Unexpected number of total threads: " + 102 " Prev Total = " + prevTotalThreadCount + 103 " Current Total = " + curTotalThreadCount + 104 " Threads added = " + numNewThreads); 105 } 106 long[] list = mbean.getAllThreadIds(); 107 if (list.length != curLiveThreadCount) { 108 fail("Array length returned by " + 109 "getAllThreadIds() = " + list.length + 110 " not matched count = " + curLiveThreadCount); 111 } 112 } 113 114 public static void main(String args[]) throws Exception { 115 if (args.length > 0 && args[0].equals("trace")) { 116 trace = true; 117 } 118 119 curTotalThreadCount = mbean.getTotalStartedThreadCount(); 120 curLiveThreadCount = mbean.getThreadCount(); 121 curPeakThreadCount = mbean.getPeakThreadCount(); 122 checkThreadCount(0, 0); 123 124 // Start all threads and wait to be sure they all are alive 125 for (int i = 0; i < ALL_THREADS; i++) { 126 setLive(i, true); 127 allThreads[i] = new MyThread(i); 128 allThreads[i].setDaemon(i < DAEMON_THREADS); 129 allThreads[i].start(); 130 } 131 // wait until all threads are started. 132 startupCheck.arriveAndAwaitAdvance(); 133 134 checkThreadCount(ALL_THREADS, 0); 135 printThreadList(); 136 137 // Check mbean now. All threads must appear in getAllThreadIds() list 138 long[] list = mbean.getAllThreadIds(); 139 140 for (int i = 0; i < ALL_THREADS; i++) { 141 long expectedId = allThreads[i].getId(); 142 boolean found = false; 143 144 if (trace) { 145 System.out.print("Looking for thread with id " + expectedId); 146 } 147 for (int j = 0; j < list.length; j++) { 148 if (expectedId == list[j]) { 149 found = true; 150 break; 151 } 152 } 153 154 if (!found) { 155 testFailed = true; 156 } 157 if (trace) { 158 if (!found) { 159 System.out.print(". TEST FAILED."); 160 } 161 System.out.println(); 162 } 163 } 164 if (trace) { 165 System.out.println(); 166 } 167 168 // Stop daemon threads, wait to be sure they all are dead, and check 169 // that they disappeared from getAllThreadIds() list 170 for (int i = 0; i < DAEMON_THREADS; i++) { 171 setLive(i, false); 172 } 173 174 // make sure the daemon threads are completely dead 175 joinDaemonThreads(); 176 177 // and check the reported thread count 178 checkThreadCount(0, DAEMON_THREADS); 179 180 // Check mbean now 181 list = mbean.getAllThreadIds(); 182 183 for (int i = 0; i < ALL_THREADS; i++) { 184 long expectedId = allThreads[i].getId(); 185 boolean found = false; 186 boolean alive = (i >= DAEMON_THREADS); 187 188 if (trace) { 189 System.out.print("Looking for thread with id " + expectedId + 190 (alive ? " expected alive." : " expected terminated.")); 191 } 192 for (int j = 0; j < list.length; j++) { 193 if (expectedId == list[j]) { 194 found = true; 195 break; 196 } 197 } 198 199 if (alive != found) { 200 testFailed = true; 201 } 202 if (trace) { 203 if (alive != found) { 204 System.out.println(" TEST FAILED."); 205 } else { 206 System.out.println(); 207 } 208 } 209 } 210 211 // Stop all threads and wait to be sure they all are dead 212 for (int i = DAEMON_THREADS; i < ALL_THREADS; i++) { 213 setLive(i, false); 214 } 215 216 // make sure the non-daemon threads are completely dead 217 joinNonDaemonThreads(); 218 219 // and check the thread count 220 checkThreadCount(0, ALL_THREADS - DAEMON_THREADS); 221 222 if (testFailed) 223 throw new RuntimeException("TEST FAILED."); 224 225 System.out.println("Test passed."); 226 } 227 228 private static void joinDaemonThreads() throws InterruptedException { 229 for (int i = 0; i < DAEMON_THREADS; i++) { 230 allThreads[i].join(); 231 } 232 } 233 234 private static void joinNonDaemonThreads() throws InterruptedException { 235 for (int i = DAEMON_THREADS; i < ALL_THREADS; i++) { 236 allThreads[i].join(); 237 } 238 } 239 240 private static void setLive(int i, boolean val) { 241 synchronized(live) { 242 live[i] = val; 243 } 244 } 245 246 private static boolean isLive(int i) { 247 synchronized(live) { 248 return live[i]; 249 } 250 } 251 252 // The MyThread thread lives as long as correspondent live[i] value is true 253 private static class MyThread extends Thread { 254 int id; 255 256 MyThread(int id) { 257 this.id = id; 258 } 259 260 public void run() { 261 // signal started 262 startupCheck.arrive(); 263 while (isLive(id)) { 264 try { 265 sleep(100); 266 } catch (InterruptedException e) { 267 System.out.println("Unexpected exception is thrown."); 268 e.printStackTrace(System.out); 269 testFailed = true; 270 } 271 } 272 } 273 } 274 }