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