0N/A/*
2362N/A * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 4892507
0N/A * @summary Basic Test for the following reset methods:
0N/A * - ThreadMXBean.resetPeakThreadCount()
0N/A * @author Mandy Chung
0N/A *
0N/A * @build ResetPeakThreadCount
0N/A * @build ThreadDump
0N/A * @run main/othervm ResetPeakThreadCount
0N/A */
0N/A
0N/Aimport java.lang.management.*;
0N/A
0N/Apublic class ResetPeakThreadCount {
0N/A // initial number of new threads started
0N/A private static final int DAEMON_THREADS_1 = 8;
0N/A private static final int EXPECTED_PEAK_DELTA_1 = 8;
0N/A
0N/A // Terminate half of the threads started
0N/A private static final int TERMINATE_1 = 4;
0N/A
0N/A // start new threads but expected the peak unchanged
0N/A private static final int DAEMON_THREADS_2 = 2;
0N/A private static final int EXPECTED_PEAK_DELTA_2 = 0;
0N/A
0N/A // peak thread count reset before starting new threads
0N/A private static final int DAEMON_THREADS_3 = 4;
0N/A private static final int EXPECTED_PEAK_DELTA_3 = 4;
0N/A
0N/A private static final int TERMINATE_2 = 8;
0N/A
0N/A private static final int ALL_THREADS = DAEMON_THREADS_1 +
0N/A DAEMON_THREADS_2 + DAEMON_THREADS_3;
0N/A // barrier for threads communication
0N/A private static Barrier barrier = new Barrier(DAEMON_THREADS_1);
0N/A
0N/A private static Thread allThreads[] = new Thread[ALL_THREADS];
0N/A private static volatile boolean live[] = new boolean[ALL_THREADS];
0N/A private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
0N/A private static boolean testFailed = false;
0N/A
0N/A public static void main(String[] argv) throws Exception {
0N/A // This test does not expect any threads to be created
0N/A // by the test harness after main() is invoked.
0N/A // The checkThreadCount() method is to produce more
0N/A // diagnostic information in case any unexpected test failure occur.
0N/A long previous = mbean.getThreadCount();
0N/A long current;
0N/A
0N/A // start DAEMON_THREADS_1 number of threads
0N/A current = startThreads(0, DAEMON_THREADS_1, EXPECTED_PEAK_DELTA_1);
0N/A
0N/A checkThreadCount(previous, current, DAEMON_THREADS_1);
0N/A previous = current;
0N/A
0N/A // terminate TERMINATE_1 number of threads and reset peak
0N/A current = terminateThreads(0, TERMINATE_1);
0N/A
0N/A checkThreadCount(previous, current, TERMINATE_1 * -1);
0N/A
0N/A previous = current;
0N/A
0N/A // start DAEMON_THREADS_2 number of threads
0N/A // expected peak is unchanged
0N/A current = startThreads(DAEMON_THREADS_1, DAEMON_THREADS_2,
0N/A EXPECTED_PEAK_DELTA_2);
0N/A
0N/A checkThreadCount(previous, current, DAEMON_THREADS_2);
0N/A previous = current;
0N/A
0N/A // Reset the peak
0N/A resetPeak(current);
0N/A
0N/A // start DAEMON_THREADS_3 number of threads
0N/A current = startThreads(DAEMON_THREADS_1 + DAEMON_THREADS_2,
0N/A DAEMON_THREADS_3, EXPECTED_PEAK_DELTA_3);
0N/A
0N/A checkThreadCount(previous, current, DAEMON_THREADS_3);
0N/A previous = current;
0N/A
0N/A // terminate TERMINATE_2 number of threads and reset peak
0N/A current = terminateThreads(TERMINATE_1, TERMINATE_2);
0N/A
0N/A checkThreadCount(previous, current, TERMINATE_2 * -1);
0N/A resetPeak(current);
0N/A
0N/A if (testFailed)
0N/A throw new RuntimeException("TEST FAILED.");
0N/A
0N/A System.out.println("Test passed");
0N/A }
0N/A
0N/A private static long startThreads(int from, int count, int delta) {
0N/A // get current peak thread count
0N/A long peak1 = mbean.getPeakThreadCount();
0N/A long current = mbean.getThreadCount();
0N/A
0N/A // Start threads and wait to be sure they all are alive
0N/A System.out.println("Starting " + count + " threads....");
0N/A barrier.set(count);
0N/A for (int i = from; i < (from + count); i++) {
0N/A live[i] = true;
0N/A allThreads[i] = new MyThread(i);
0N/A allThreads[i].setDaemon(true);
0N/A allThreads[i].start();
0N/A }
0N/A // wait until all threads have started.
0N/A barrier.await();
0N/A
0N/A // get peak thread count after daemon threads have started
0N/A long peak2 = mbean.getPeakThreadCount();
0N/A
0N/A System.out.println(" Current = " + mbean.getThreadCount() +
0N/A " Peak before = " + peak1 + " after: " + peak2);
0N/A
0N/A if (peak2 != (peak1 + delta)) {
0N/A throw new RuntimeException("Current Peak = " + peak2 +
0N/A " Expected to be == previous peak = " + peak1 + " + " +
0N/A delta);
0N/A }
0N/A // wait until the current thread count gets incremented
0N/A while (mbean.getThreadCount() < (current + count)) {
0N/A try {
0N/A Thread.sleep(100);
0N/A } catch (InterruptedException e) {
0N/A e.printStackTrace();
0N/A System.out.println("Unexpected exception.");
0N/A testFailed = true;
0N/A }
0N/A }
0N/A current = mbean.getThreadCount();
0N/A System.out.println(" Live thread count before returns " + current);
0N/A return current;
0N/A }
0N/A
0N/A private static long terminateThreads(int from, int count) {
0N/A // get current peak thread count
0N/A long peak1 = mbean.getPeakThreadCount();
0N/A long current = mbean.getThreadCount();
0N/A
0N/A // Stop daemon threads and wait to be sure they all are dead
0N/A System.out.println("Terminating " + count + " threads....");
0N/A barrier.set(count);
0N/A for (int i = from; i < (from+count); i++) {
0N/A live[i] = false;
0N/A }
0N/A // wait until daemon threads terminated.
0N/A barrier.await();
0N/A
0N/A // get peak thread count after daemon threads have terminated
0N/A long peak2 = mbean.getPeakThreadCount();
0N/A // assuming no system thread is added
0N/A if (peak2 != peak1) {
0N/A throw new RuntimeException("Current Peak = " + peak2 +
0N/A " Expected to be = previous peak = " + peak1);
0N/A }
0N/A
0N/A // wait until the current thread count gets decremented
0N/A while (mbean.getThreadCount() > (current - count)) {
0N/A try {
0N/A Thread.sleep(100);
0N/A } catch (InterruptedException e) {
0N/A e.printStackTrace();
0N/A System.out.println("Unexpected exception.");
0N/A testFailed = true;
0N/A }
0N/A }
0N/A
0N/A current = mbean.getThreadCount();
0N/A System.out.println(" Live thread count before returns " + current);
0N/A return current;
0N/A }
0N/A
0N/A private static void resetPeak(long expectedCount) {
0N/A long peak3 = mbean.getPeakThreadCount();
0N/A long current = mbean.getThreadCount();
0N/A
0N/A // Nightly testing showed some intermittent failure.
0N/A // Check here to get diagnostic information if some strange
0N/A // behavior occurs.
0N/A checkThreadCount(expectedCount, current, 0);
0N/A
0N/A // Reset peak thread count
0N/A mbean.resetPeakThreadCount();
0N/A
0N/A long afterResetPeak = mbean.getPeakThreadCount();
0N/A long afterResetCurrent = mbean.getThreadCount();
0N/A System.out.println("Reset peak before = " + peak3 +
0N/A " current = " + current +
0N/A " after reset peak = " + afterResetPeak +
0N/A " current = " + afterResetCurrent);
0N/A
0N/A if (afterResetPeak != current) {
0N/A throw new RuntimeException("Current Peak after reset = " +
0N/A afterResetPeak +
0N/A " Expected to be = current count = " + current);
0N/A }
0N/A }
0N/A
0N/A private static void checkThreadCount(long previous, long current, int expectedDelta) {
0N/A if (current != previous + expectedDelta) {
0N/A System.out.println("***** Unexpected thread count:" +
0N/A " previous = " + previous +
0N/A " current = " + current +
0N/A " delta = " + expectedDelta + "*****");
0N/A ThreadDump.threadDump();
0N/A }
0N/A }
0N/A
0N/A // The MyThread thread lives as long as correspondent live[i] value is true
0N/A private static class MyThread extends Thread {
0N/A int id;
0N/A
0N/A MyThread(int id) {
0N/A this.id = id;
0N/A }
0N/A
0N/A public void run() {
0N/A // signal started
0N/A barrier.signal();
0N/A while (live[id]) {
0N/A try {
0N/A sleep(100);
0N/A } catch (InterruptedException e) {
0N/A System.out.println("Unexpected exception is thrown.");
0N/A e.printStackTrace(System.out);
0N/A testFailed = true;
0N/A }
0N/A }
0N/A // signal about to exit
0N/A barrier.signal();
0N/A }
0N/A }
0N/A
0N/A}