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