Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8131745: java/lang/management/ThreadMXBean/AllThreadIds.java still fa…
…ils intermittently

Reviewed-by: sspitsyn, amenkov
  • Loading branch information
Daniil Titov committed Jun 8, 2020
1 parent b073038 commit ea9aeda5ee89c02add8c69c1045659dd9eac5154
Showing with 58 additions and 116 deletions.
  1. +0 −1 test/jdk/ProblemList.txt
  2. +58 −115 test/jdk/java/lang/management/ThreadMXBean/AllThreadIds.java
@@ -578,7 +578,6 @@ java/lang/management/MemoryMXBean/Pending.java 8158837 generic-
java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all

java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8081652 generic-all
java/lang/management/ThreadMXBean/AllThreadIds.java 8131745 generic-all

javax/management/monitor/DerivedGaugeMonitorTest.java 8042211 generic-all
javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java 8227337 generic-all
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,10 @@
*/

import java.lang.management.*;
import java.time.Instant;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Phaser;
import java.util.function.Supplier;

@@ -61,12 +64,14 @@ public String toString() {
static final int ALL_THREADS = DAEMON_THREADS + USER_THREADS;
private static final boolean live[] = new boolean[ALL_THREADS];
private static final Thread allThreads[] = new Thread[ALL_THREADS];
private static final Set<Long> allThreadIds = new HashSet<>();

private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
private static boolean testFailed = false;
private static boolean trace = false;

private static long prevTotalThreadCount = 0;
private static int prevLiveThreadCount = 0;
private static long prevLiveTestThreadCount = 0;
private static int prevPeakThreadCount = 0;

private static final Phaser startupCheck = new Phaser(ALL_THREADS + 1);
@@ -95,9 +100,11 @@ private static void checkAllThreadsAlive() throws Exception {
// Start all threads and wait to be sure they all are alive
for (int i = 0; i < ALL_THREADS; i++) {
setLive(i, true);
allThreads[i] = new MyThread(i);
allThreads[i].setDaemon(i < DAEMON_THREADS);
allThreads[i].start();
Thread thread = new MyThread(i);
thread.setDaemon(i < DAEMON_THREADS);
thread.start();
allThreadIds.add(thread.getId());
allThreads[i] = thread;
}
// wait until all threads are started.
startupCheck.arriveAndAwaitAdvance();
@@ -107,30 +114,13 @@ private static void checkAllThreadsAlive() throws Exception {
printThreadList();
}
// Check mbean now. All threads must appear in getAllThreadIds() list
long[] list = mbean.getAllThreadIds();

for (int i = 0; i < ALL_THREADS; i++) {
long expectedId = allThreads[i].getId();
boolean found = false;
Set<Long> currentThreadIds = new HashSet<>();
Arrays.stream(mbean.getAllThreadIds()).forEach(currentThreadIds::add);

if (!currentThreadIds.containsAll(allThreadIds)) {
testFailed = true;
if (trace) {
System.out.print("Looking for thread with id " + expectedId);
}
for (int j = 0; j < list.length; j++) {
if (expectedId == list[j]) {
found = true;
break;
}
}

if (!found) {
testFailed = true;
}
if (trace) {
if (!found) {
System.out.print(". TEST FAILED.");
}
System.out.println();
System.out.print(". TEST FAILED.");
}
}
if (trace) {
@@ -201,112 +191,65 @@ private static void checkAllThreadsDead() throws Exception {
}

private static void checkThreadCount(int numNewThreads,
int numTerminatedThreads)
throws Exception {

int numTerminatedThreads) {
checkLiveThreads(numNewThreads, numTerminatedThreads);
checkPeakThreads(numNewThreads);
checkTotalThreads(numNewThreads);
checkThreadIds();
checkThreadIds(numNewThreads, numTerminatedThreads);
}

private static void checkLiveThreads(int numNewThreads,
int numTerminatedThreads)
throws InterruptedException {
int numTerminatedThreads) {
int diff = numNewThreads - numTerminatedThreads;

waitTillEquals(
diff + prevLiveThreadCount,
()->(long)mbean.getThreadCount(),
"Unexpected number of live threads: " +
" Prev live = %1$d Current live = ${provided} Threads added = %2$d" +
" Threads terminated = %3$d",
()->prevLiveThreadCount,
()->numNewThreads,
()->numTerminatedThreads
);
long threadCount = mbean.getThreadCount();
long expectedThreadCount = prevLiveTestThreadCount + diff;
// Check that number of live test threads is no less
// than number of all threads returned by mbean.getThreadCount()
if (threadCount < expectedThreadCount) {
testFailed = true;
System.err.println(MessageFormat.format("Unexpected number of threads count %d." +
"The expected number is %d or greater", threadCount, expectedThreadCount));
}
}

private static void checkPeakThreads(int numNewThreads)
throws InterruptedException {

waitTillEquals(numNewThreads + prevPeakThreadCount,
()->(long)mbean.getPeakThreadCount(),
"Unexpected number of peak threads: " +
" Prev peak = %1$d Current peak = ${provided} Threads added = %2$d",
()->prevPeakThreadCount,
()->numNewThreads
);
private static void checkPeakThreads(int numNewThreads) {
long peakThreadCount = mbean.getPeakThreadCount();
long expectedThreadCount = Math.max(prevPeakThreadCount, numNewThreads);
if (peakThreadCount < expectedThreadCount) {
testFailed = true;
System.err.println(MessageFormat.format("Unexpected number of peak threads count %d." +
"The expected number is %d or greater", peakThreadCount, expectedThreadCount));
}
}

private static void checkTotalThreads(int numNewThreads)
throws InterruptedException {

waitTillEquals(numNewThreads + prevTotalThreadCount,
()->mbean.getTotalStartedThreadCount(),
"Unexpected number of total threads: " +
" Prev Total = %1$d Current Total = ${provided} Threads added = %2$d",
()->prevTotalThreadCount,
()->numNewThreads
);
private static void checkTotalThreads(int numNewThreads) {
long totalThreadCount = mbean.getTotalStartedThreadCount();
long expectedThreadCount = prevTotalThreadCount + numNewThreads;
if (totalThreadCount < expectedThreadCount) {
testFailed = true;
System.err.println(MessageFormat.format("Unexpected number of total threads %d." +
"The expected number is %d or greater", totalThreadCount, expectedThreadCount));
}
}

private static void checkThreadIds() throws InterruptedException {
long[] list = mbean.getAllThreadIds();

waitTillEquals(
list.length,
()->(long)mbean.getThreadCount(),
"Array length returned by " +
"getAllThreadIds() = %1$d not matched count = ${provided}",
()->list.length
);
private static void checkThreadIds(int numNewThreads, int numTerminatedThreads) {
int threadCount = mbean.getAllThreadIds().length;
int expectedThreadCount = numNewThreads - numTerminatedThreads;
if (threadCount < expectedThreadCount) {
testFailed = true;
System.err.println(MessageFormat.format("Unexpected number of threads %d." +
"The expected number is %d or greater", threadCount, expectedThreadCount));
}
}

/**
* Waits till the <em>expectedVal</em> equals to the <em>retrievedVal</em>.
* It will report a status message on the first occasion of the value mismatch
* and then, subsequently, when the <em>retrievedVal</em> value changes.
* @param expectedVal The value to wait for
* @param retrievedVal The supplier of the value to check against the <em>expectedVal</em>
* @param msgFormat The formatted message to be printed in case of mismatch
* @param msgArgs The parameters to the formatted message
* @throws InterruptedException
*/
private static void waitTillEquals(long expectedVal, Supplier<Long> retrievedVal,
String msgFormat, Supplier<Object> ... msgArgs)
throws InterruptedException {
Object[] args = null;

long countPrev = -1;
while (true) {
Long count = retrievedVal.get();
if (count == expectedVal) break;
if (countPrev == -1 || countPrev != count) {
if (args == null) {
args = new Object[msgArgs.length];
for(int i=0; i < msgArgs.length; i++) {
args[i] = new ArgWrapper<>((Supplier<Object>)msgArgs[i]);
}
}
System.err.format("TS: %s\n", Instant.now());
System.err.format(
msgFormat
.replace("${provided}", String.valueOf(count))
.replace("$d", "$s"),
args
).flush();
printThreadList();
System.err.println("\nRetrying ...\n");
}
countPrev = count;
Thread.sleep(1);
}
private static long getTestThreadCount() {
return Thread.getAllStackTraces().keySet().stream().filter(
thread -> thread.isAlive() && allThreadIds.contains(thread.getId())).count();
}

private static void updateCounters() {
prevTotalThreadCount = mbean.getTotalStartedThreadCount();
prevLiveThreadCount = mbean.getThreadCount();
prevLiveTestThreadCount = getTestThreadCount();
prevPeakThreadCount = mbean.getPeakThreadCount();
}

0 comments on commit ea9aeda

Please sign in to comment.