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 mbean.getThreadCount()
  28  *                             mbean.getTotalStartedThreadCount()
  29  *                             mbean.getPeakThreadCount()
  30  *                             mbean.getDaemonThreadCount()
  31  * @author  Alexei Guibadoulline
  32  *
  33  * @modules java.management
  34  * @run main ThreadCounts
  35  */
  36 
  37 import java.lang.management.*;
  38 
  39 public class ThreadCounts {
  40     static final int DAEMON_THREADS = 21;
  41     static final int USER_THREADS_1 = 11;
  42     static final int USER_THREADS_2 = 9;
  43     static final int USER_THREADS = USER_THREADS_1 + USER_THREADS_2;
  44     static final int ALL_THREADS = DAEMON_THREADS + USER_THREADS;
  45     private static volatile boolean live[] = new boolean[ALL_THREADS];
  46     private ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
  47     private static boolean testFailed = false;
  48 
  49     // barrier for threads communication
  50     private static Barrier barrier = new Barrier(DAEMON_THREADS);
  51 
  52     public static void main(String argv[]) {
  53         ThreadCounts test = new ThreadCounts();
  54         Thread allThreads[] = new Thread[ALL_THREADS];
  55 
  56         // Start DAEMON_THREADS threads and wait to be sure they all are alive
  57         barrier.set(DAEMON_THREADS);
  58         for (int i = 0; i < DAEMON_THREADS; i++) {
  59             live[i] = true;
  60             allThreads[i] = new MyThread(i);
  61             allThreads[i].setDaemon(true);
  62             allThreads[i].start();
  63         }
  64         // wait until all threads have started.
  65         barrier.await();
  66 
  67 
  68         System.out.println("Number of daemon threads added = " +
  69                            DAEMON_THREADS);
  70         // Check mbean now
  71         if ( (!test.checkCount  (DAEMON_THREADS)) ||
  72              (!test.checkCreated(DAEMON_THREADS)) ||
  73              (!test.checkPeak   (DAEMON_THREADS)) ||
  74              (!test.checkDaemon (DAEMON_THREADS))
  75            )
  76             testFailed = true;
  77 
  78         // Start USER_THREADS_1 threads and wait to be sure they all are alive
  79         barrier.set(USER_THREADS_1);
  80         for (int i = DAEMON_THREADS; i < DAEMON_THREADS + USER_THREADS_1; i++) {
  81             live[i] = true;
  82             allThreads[i] = new MyThread(i);
  83             allThreads[i].setDaemon(false);
  84             allThreads[i].start();
  85         }
  86         // wait until user1 threads have started.
  87         barrier.await();
  88 
  89         System.out.println("Number of threads added = " +
  90                            USER_THREADS_1);
  91         // Check mbean now
  92         if ( (!test.checkCount  (DAEMON_THREADS + USER_THREADS_1)) ||
  93              (!test.checkCreated(DAEMON_THREADS + USER_THREADS_1)) ||
  94              (!test.checkPeak   (DAEMON_THREADS + USER_THREADS_1)) ||
  95              (!test.checkDaemon (DAEMON_THREADS))
  96            )
  97             testFailed = true;
  98 
  99         // Stop daemon threads and wait to be sure they all are dead
 100         barrier.set(DAEMON_THREADS);
 101         for (int i = 0; i < DAEMON_THREADS; i++) {
 102             live[i] = false;
 103         }
 104         // wait until daemon threads terminated.
 105         barrier.await();
 106 
 107         System.out.println("Daemon threads terminated.");
 108         // Check mbean now
 109         if ( (!test.checkCount  (USER_THREADS_1))                  ||
 110              (!test.checkCreated(DAEMON_THREADS + USER_THREADS_1)) ||
 111              (!test.checkPeak   (DAEMON_THREADS + USER_THREADS_1)) ||
 112              (!test.checkDaemon (0))
 113            )
 114             testFailed = true;
 115 
 116         // Start USER_THREADS_2 threads and wait to be sure they all are alive
 117         barrier.set(USER_THREADS_2);
 118         for (int i = DAEMON_THREADS + USER_THREADS_1; i < ALL_THREADS; i++) {
 119             live[i] = true;
 120             allThreads[i] = new MyThread(i);
 121             allThreads[i].setDaemon(false);
 122             allThreads[i].start();
 123         }
 124         // wait until user2 threads have started.
 125         barrier.await();
 126 
 127         System.out.println("Number of threads added = " +
 128                            USER_THREADS_2);
 129         // Check mbean now
 130         if ( (!test.checkCount  (USER_THREADS_1 + USER_THREADS_2)) ||
 131              (!test.checkCreated(ALL_THREADS))                     ||
 132              (!test.checkPeak   (DAEMON_THREADS + USER_THREADS_1)) ||
 133              (!test.checkDaemon (0))
 134            )
 135             testFailed = true;
 136 
 137         // Stop user1 threads and wait to be sure they all are dead
 138         barrier.set(USER_THREADS_1);
 139         for (int i = DAEMON_THREADS; i < DAEMON_THREADS + USER_THREADS_1; i++) {
 140             live[i] = false;
 141         }
 142         // wait until user1 threads terminated.
 143         barrier.await();
 144 
 145         System.out.println("Number of threads terminated = " +
 146                            USER_THREADS_1);
 147         // Check mbean now
 148         if ( (!test.checkCount  (USER_THREADS_2))                  ||
 149              (!test.checkCreated(ALL_THREADS))                     ||
 150              (!test.checkPeak   (DAEMON_THREADS + USER_THREADS_1)) ||
 151              (!test.checkDaemon (0))
 152            )
 153             testFailed = true;
 154 
 155         // Stop user2 threads and wait to be sure they all are dead
 156         barrier.set(USER_THREADS_2);
 157         for (int i = DAEMON_THREADS + USER_THREADS_1; i < ALL_THREADS; i++) {
 158             live[i] = false;
 159         }
 160         // wait until user2 threads terminated.
 161         barrier.await();
 162 
 163         System.out.println("Number of threads terminated = " +
 164                            USER_THREADS_2);
 165         // Check mbean now
 166         if ( (!test.checkCount  (0))                               ||
 167              (!test.checkCreated(ALL_THREADS))                     ||
 168              (!test.checkPeak   (DAEMON_THREADS + USER_THREADS_1)) ||
 169              (!test.checkDaemon (0))
 170            )
 171             testFailed = true;
 172 
 173         if (testFailed)
 174             throw new RuntimeException("TEST FAILED.");
 175 
 176         System.out.println("Test passed.");
 177     }
 178 
 179     // Nobody knows how many threads are in the JVM in the exact moment. The
 180     // only thing to check for sure is minimal number of threads alive (or
 181     // created) in the application
 182     private boolean checkCount(long min) {
 183         long result = mbean.getThreadCount();
 184 
 185         if (result < min) {
 186             System.err.println("TEST FAILED: " +
 187                                "Minimal number of live threads is " +
 188                                 min +
 189                                 ". ThreadMXBean.getThreadCount() returned " +
 190                                 result);
 191             return false;
 192         }
 193         return true;
 194     }
 195 
 196     private boolean checkCreated(long min) {
 197         long result = mbean.getTotalStartedThreadCount();
 198 
 199         if (result < min) {
 200             System.err.println("TEST FAILED: " +
 201                                "Minimal number of created threads is " +
 202                                 min +
 203                                 ". ThreadMXBean.getTotalStartedThreadCount() "+
 204                                 "returned " + result);
 205             return false;
 206         }
 207         return true;
 208     }
 209 
 210     private boolean checkPeak(long min) {
 211         long result = mbean.getPeakThreadCount();
 212 
 213         if (result < min) {
 214             System.err.println("TEST FAILED: " +
 215                                "Minimal peak thread count is " +
 216                                 min +
 217                                 ". ThreadMXBean.getPeakThreadCount() "+
 218                                 "returned " + result);
 219             return false;
 220         }
 221         return true;
 222     }
 223 
 224     private boolean checkDaemon(long min) {
 225         long result = mbean.getDaemonThreadCount();
 226 
 227         if (result < min) {
 228             System.err.println("TEST FAILED: " +
 229                                "Minimal number of daemon thread count is " +
 230                                 min +
 231                                "ThreadMXBean.getDaemonThreadCount() returned "
 232                                 + result);
 233             return false;
 234         }
 235         return true;
 236     }
 237 
 238     // The MyThread thread lives as long as correspondent live[i] value is true
 239     private static class MyThread extends Thread {
 240         int id;
 241 
 242         MyThread(int id) {
 243             this.id = id;
 244         }
 245 
 246         public void run() {
 247             // signal started
 248             barrier.signal();
 249             while (live[id]) {
 250                 try {
 251                     sleep(100);
 252                 } catch (InterruptedException e) {
 253                     System.out.println("Unexpected exception is thrown.");
 254                     e.printStackTrace(System.out);
 255                     testFailed = true;
 256                 }
 257             }
 258             // signal about to exit
 259             barrier.signal();
 260         }
 261     }
 262 }