Path: blob/master/test/jdk/java/lang/management/ThreadMXBean/AllThreadIds.java
41152 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 453053826* @key intermittent27* @summary Basic unit test of ThreadMXBean.getAllThreadIds()28* @author Alexei Guibadoulline and Mandy Chung29*30* @run main/othervm AllThreadIds31*/3233import java.lang.management.*;34import java.text.MessageFormat;35import java.util.Arrays;36import java.util.HashSet;37import java.util.Set;38import java.util.concurrent.Phaser;39import java.util.function.Supplier;4041public class AllThreadIds {42/**43* A supplier wrapper for the delayed format printing.44* The supplied value will have to be formatted as <em>$s</em>45* @param <T> The wrapped type46*/47private static final class ArgWrapper<T> {48private final Supplier<T> val;4950public ArgWrapper(Supplier<T> val) {51this.val = val;52}5354@Override55public String toString() {56T resolved = val.get();57return resolved != null ? resolved.toString() : null;58}59}6061static final int DAEMON_THREADS = 20;62static final int USER_THREADS = 5;63static final int ALL_THREADS = DAEMON_THREADS + USER_THREADS;64private static final boolean live[] = new boolean[ALL_THREADS];65private static final Thread allThreads[] = new Thread[ALL_THREADS];66private static final Set<Long> allThreadIds = new HashSet<>();6768private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();69private static boolean testFailed = false;70private static boolean trace = false;7172private static long prevTotalThreadCount = 0;73private static long prevLiveTestThreadCount = 0;74private static int prevPeakThreadCount = 0;7576private static final Phaser startupCheck = new Phaser(ALL_THREADS + 1);7778private static void printThreadList() {79long[] list = mbean.getAllThreadIds();80for (int i = 1; i <= list.length; i++) {81System.out.println(i + ": Thread id = " + list[i-1]);82}83for (int i = 0; i < ALL_THREADS; i++) {84Thread t = allThreads[i];85System.out.println(t.getName() + " Id = " + t.getId() +86" die = " + live[i] +87" alive = " + t.isAlive());88}89}9091private static void checkInitialState() throws Exception {92updateCounters();93checkThreadCount(0, 0);94}9596private static void checkAllThreadsAlive() throws Exception {97updateCounters();9899// Start all threads and wait to be sure they all are alive100for (int i = 0; i < ALL_THREADS; i++) {101setLive(i, true);102Thread thread = new MyThread(i);103thread.setDaemon(i < DAEMON_THREADS);104thread.start();105allThreadIds.add(thread.getId());106allThreads[i] = thread;107}108// wait until all threads are started.109startupCheck.arriveAndAwaitAdvance();110111checkThreadCount(ALL_THREADS, 0);112if (trace) {113printThreadList();114}115// Check mbean now. All threads must appear in getAllThreadIds() list116Set<Long> currentThreadIds = new HashSet<>();117Arrays.stream(mbean.getAllThreadIds()).forEach(currentThreadIds::add);118119if (!currentThreadIds.containsAll(allThreadIds)) {120testFailed = true;121if (trace) {122System.out.print(". TEST FAILED.");123}124}125if (trace) {126System.out.println();127}128}129130private static void checkDaemonThreadsDead() throws Exception {131updateCounters();132133// Stop daemon threads, wait to be sure they all are dead, and check134// that they disappeared from getAllThreadIds() list135for (int i = 0; i < DAEMON_THREADS; i++) {136setLive(i, false);137}138139// make sure the daemon threads are completely dead140joinDaemonThreads();141142// and check the reported thread count143checkThreadCount(0, DAEMON_THREADS);144145// Check mbean now146long[] list = mbean.getAllThreadIds();147148for (int i = 0; i < ALL_THREADS; i++) {149long expectedId = allThreads[i].getId();150boolean found = false;151boolean alive = (i >= DAEMON_THREADS);152153if (trace) {154System.out.print("Looking for thread with id " + expectedId +155(alive ? " expected alive." : " expected terminated."));156}157for (int j = 0; j < list.length; j++) {158if (expectedId == list[j]) {159found = true;160break;161}162}163164if (alive != found) {165testFailed = true;166}167if (trace) {168if (alive != found) {169System.out.println(" TEST FAILED.");170} else {171System.out.println();172}173}174}175}176177private static void checkAllThreadsDead() throws Exception {178updateCounters();179180// Stop all threads and wait to be sure they all are dead181for (int i = DAEMON_THREADS; i < ALL_THREADS; i++) {182setLive(i, false);183}184185// make sure the non-daemon threads are completely dead186joinNonDaemonThreads();187188// and check the thread count189checkThreadCount(0, ALL_THREADS - DAEMON_THREADS);190}191192private static void checkThreadCount(int numNewThreads,193int numTerminatedThreads) {194checkLiveThreads(numNewThreads, numTerminatedThreads);195checkPeakThreads(numNewThreads);196checkTotalThreads(numNewThreads);197checkThreadIds(numNewThreads, numTerminatedThreads);198}199200private static void checkLiveThreads(int numNewThreads,201int numTerminatedThreads) {202int diff = numNewThreads - numTerminatedThreads;203long threadCount = mbean.getThreadCount();204long expectedThreadCount = prevLiveTestThreadCount + diff;205// Check that number of live test threads is no less206// than number of all threads returned by mbean.getThreadCount()207if (threadCount < expectedThreadCount) {208testFailed = true;209System.err.println(MessageFormat.format("Unexpected number of threads count %d." +210"The expected number is %d or greater", threadCount, expectedThreadCount));211}212}213214private static void checkPeakThreads(int numNewThreads) {215long peakThreadCount = mbean.getPeakThreadCount();216long expectedThreadCount = Math.max(prevPeakThreadCount, numNewThreads);217if (peakThreadCount < expectedThreadCount) {218testFailed = true;219System.err.println(MessageFormat.format("Unexpected number of peak threads count %d." +220"The expected number is %d or greater", peakThreadCount, expectedThreadCount));221}222}223224private static void checkTotalThreads(int numNewThreads) {225long totalThreadCount = mbean.getTotalStartedThreadCount();226long expectedThreadCount = prevTotalThreadCount + numNewThreads;227if (totalThreadCount < expectedThreadCount) {228testFailed = true;229System.err.println(MessageFormat.format("Unexpected number of total threads %d." +230"The expected number is %d or greater", totalThreadCount, expectedThreadCount));231}232}233234private static void checkThreadIds(int numNewThreads, int numTerminatedThreads) {235int threadCount = mbean.getAllThreadIds().length;236int expectedThreadCount = numNewThreads - numTerminatedThreads;237if (threadCount < expectedThreadCount) {238testFailed = true;239System.err.println(MessageFormat.format("Unexpected number of threads %d." +240"The expected number is %d or greater", threadCount, expectedThreadCount));241}242}243244private static long getTestThreadCount() {245return Thread.getAllStackTraces().keySet().stream().filter(246thread -> thread.isAlive() && allThreadIds.contains(thread.getId())).count();247}248249private static void updateCounters() {250prevTotalThreadCount = mbean.getTotalStartedThreadCount();251prevLiveTestThreadCount = getTestThreadCount();252prevPeakThreadCount = mbean.getPeakThreadCount();253}254255public static void main(String args[]) throws Exception {256if (args.length > 0 && args[0].equals("trace")) {257trace = true;258}259260checkInitialState();261checkAllThreadsAlive();262checkDaemonThreadsDead();263checkAllThreadsDead();264265if (testFailed)266throw new RuntimeException("TEST FAILED.");267268System.out.println("Test passed.");269}270271private static void joinDaemonThreads() throws InterruptedException {272for (int i = 0; i < DAEMON_THREADS; i++) {273allThreads[i].join();274}275}276277private static void joinNonDaemonThreads() throws InterruptedException {278for (int i = DAEMON_THREADS; i < ALL_THREADS; i++) {279allThreads[i].join();280}281}282283private static void setLive(int i, boolean val) {284synchronized(live) {285live[i] = val;286}287}288289private static boolean isLive(int i) {290synchronized(live) {291return live[i];292}293}294295// The MyThread thread lives as long as correspondent live[i] value is true296private static class MyThread extends Thread {297int id;298299MyThread(int id) {300this.id = id;301}302303public void run() {304// signal started305startupCheck.arrive();306while (isLive(id)) {307try {308sleep(100);309} catch (InterruptedException e) {310System.out.println("Unexpected exception is thrown.");311e.printStackTrace(System.out);312testFailed = true;313}314}315}316}317}318319320