Skip to content

Commit 7acc631

Browse files
committed
8131745: java/lang/management/ThreadMXBean/AllThreadIds.java still fails intermittently
Reviewed-by: mdoerr Backport-of: ea9aeda
1 parent 3fb7528 commit 7acc631

File tree

2 files changed

+58
-117
lines changed

2 files changed

+58
-117
lines changed

test/jdk/ProblemList.txt

-2
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,6 @@ java/lang/instrument/BootClassPath/BootClassPathTest.sh 8072130 macosx-a
536536
java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all
537537
java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all
538538

539-
java/lang/management/ThreadMXBean/AllThreadIds.java 8131745 generic-all
540-
541539
############################################################################
542540

543541
# jdk_io

test/jdk/java/lang/management/ThreadMXBean/AllThreadIds.java

+58-115
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,10 @@
3232
*/
3333

3434
import java.lang.management.*;
35-
import java.time.Instant;
35+
import java.text.MessageFormat;
36+
import java.util.Arrays;
37+
import java.util.HashSet;
38+
import java.util.Set;
3639
import java.util.concurrent.Phaser;
3740
import java.util.function.Supplier;
3841

@@ -61,12 +64,14 @@ public String toString() {
6164
static final int ALL_THREADS = DAEMON_THREADS + USER_THREADS;
6265
private static final boolean live[] = new boolean[ALL_THREADS];
6366
private static final Thread allThreads[] = new Thread[ALL_THREADS];
67+
private static final Set<Long> allThreadIds = new HashSet<>();
68+
6469
private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
6570
private static boolean testFailed = false;
6671
private static boolean trace = false;
6772

6873
private static long prevTotalThreadCount = 0;
69-
private static int prevLiveThreadCount = 0;
74+
private static long prevLiveTestThreadCount = 0;
7075
private static int prevPeakThreadCount = 0;
7176

7277
private static final Phaser startupCheck = new Phaser(ALL_THREADS + 1);
@@ -95,9 +100,11 @@ private static void checkAllThreadsAlive() throws Exception {
95100
// Start all threads and wait to be sure they all are alive
96101
for (int i = 0; i < ALL_THREADS; i++) {
97102
setLive(i, true);
98-
allThreads[i] = new MyThread(i);
99-
allThreads[i].setDaemon(i < DAEMON_THREADS);
100-
allThreads[i].start();
103+
Thread thread = new MyThread(i);
104+
thread.setDaemon(i < DAEMON_THREADS);
105+
thread.start();
106+
allThreadIds.add(thread.getId());
107+
allThreads[i] = thread;
101108
}
102109
// wait until all threads are started.
103110
startupCheck.arriveAndAwaitAdvance();
@@ -107,30 +114,13 @@ private static void checkAllThreadsAlive() throws Exception {
107114
printThreadList();
108115
}
109116
// Check mbean now. All threads must appear in getAllThreadIds() list
110-
long[] list = mbean.getAllThreadIds();
111-
112-
for (int i = 0; i < ALL_THREADS; i++) {
113-
long expectedId = allThreads[i].getId();
114-
boolean found = false;
117+
Set<Long> currentThreadIds = new HashSet<>();
118+
Arrays.stream(mbean.getAllThreadIds()).forEach(currentThreadIds::add);
115119

120+
if (!currentThreadIds.containsAll(allThreadIds)) {
121+
testFailed = true;
116122
if (trace) {
117-
System.out.print("Looking for thread with id " + expectedId);
118-
}
119-
for (int j = 0; j < list.length; j++) {
120-
if (expectedId == list[j]) {
121-
found = true;
122-
break;
123-
}
124-
}
125-
126-
if (!found) {
127-
testFailed = true;
128-
}
129-
if (trace) {
130-
if (!found) {
131-
System.out.print(". TEST FAILED.");
132-
}
133-
System.out.println();
123+
System.out.print(". TEST FAILED.");
134124
}
135125
}
136126
if (trace) {
@@ -201,112 +191,65 @@ private static void checkAllThreadsDead() throws Exception {
201191
}
202192

203193
private static void checkThreadCount(int numNewThreads,
204-
int numTerminatedThreads)
205-
throws Exception {
206-
194+
int numTerminatedThreads) {
207195
checkLiveThreads(numNewThreads, numTerminatedThreads);
208196
checkPeakThreads(numNewThreads);
209197
checkTotalThreads(numNewThreads);
210-
checkThreadIds();
198+
checkThreadIds(numNewThreads, numTerminatedThreads);
211199
}
212200

213201
private static void checkLiveThreads(int numNewThreads,
214-
int numTerminatedThreads)
215-
throws InterruptedException {
202+
int numTerminatedThreads) {
216203
int diff = numNewThreads - numTerminatedThreads;
217-
218-
waitTillEquals(
219-
diff + prevLiveThreadCount,
220-
()->(long)mbean.getThreadCount(),
221-
"Unexpected number of live threads: " +
222-
" Prev live = %1$d Current live = ${provided} Threads added = %2$d" +
223-
" Threads terminated = %3$d",
224-
()->prevLiveThreadCount,
225-
()->numNewThreads,
226-
()->numTerminatedThreads
227-
);
204+
long threadCount = mbean.getThreadCount();
205+
long expectedThreadCount = prevLiveTestThreadCount + diff;
206+
// Check that number of live test threads is no less
207+
// than number of all threads returned by mbean.getThreadCount()
208+
if (threadCount < expectedThreadCount) {
209+
testFailed = true;
210+
System.err.println(MessageFormat.format("Unexpected number of threads count %d." +
211+
"The expected number is %d or greater", threadCount, expectedThreadCount));
212+
}
228213
}
229214

230-
private static void checkPeakThreads(int numNewThreads)
231-
throws InterruptedException {
232-
233-
waitTillEquals(numNewThreads + prevPeakThreadCount,
234-
()->(long)mbean.getPeakThreadCount(),
235-
"Unexpected number of peak threads: " +
236-
" Prev peak = %1$d Current peak = ${provided} Threads added = %2$d",
237-
()->prevPeakThreadCount,
238-
()->numNewThreads
239-
);
215+
private static void checkPeakThreads(int numNewThreads) {
216+
long peakThreadCount = mbean.getPeakThreadCount();
217+
long expectedThreadCount = Math.max(prevPeakThreadCount, numNewThreads);
218+
if (peakThreadCount < expectedThreadCount) {
219+
testFailed = true;
220+
System.err.println(MessageFormat.format("Unexpected number of peak threads count %d." +
221+
"The expected number is %d or greater", peakThreadCount, expectedThreadCount));
222+
}
240223
}
241224

242-
private static void checkTotalThreads(int numNewThreads)
243-
throws InterruptedException {
244-
245-
waitTillEquals(numNewThreads + prevTotalThreadCount,
246-
()->mbean.getTotalStartedThreadCount(),
247-
"Unexpected number of total threads: " +
248-
" Prev Total = %1$d Current Total = ${provided} Threads added = %2$d",
249-
()->prevTotalThreadCount,
250-
()->numNewThreads
251-
);
225+
private static void checkTotalThreads(int numNewThreads) {
226+
long totalThreadCount = mbean.getTotalStartedThreadCount();
227+
long expectedThreadCount = prevTotalThreadCount + numNewThreads;
228+
if (totalThreadCount < expectedThreadCount) {
229+
testFailed = true;
230+
System.err.println(MessageFormat.format("Unexpected number of total threads %d." +
231+
"The expected number is %d or greater", totalThreadCount, expectedThreadCount));
232+
}
252233
}
253234

254-
private static void checkThreadIds() throws InterruptedException {
255-
long[] list = mbean.getAllThreadIds();
256-
257-
waitTillEquals(
258-
list.length,
259-
()->(long)mbean.getThreadCount(),
260-
"Array length returned by " +
261-
"getAllThreadIds() = %1$d not matched count = ${provided}",
262-
()->list.length
263-
);
235+
private static void checkThreadIds(int numNewThreads, int numTerminatedThreads) {
236+
int threadCount = mbean.getAllThreadIds().length;
237+
int expectedThreadCount = numNewThreads - numTerminatedThreads;
238+
if (threadCount < expectedThreadCount) {
239+
testFailed = true;
240+
System.err.println(MessageFormat.format("Unexpected number of threads %d." +
241+
"The expected number is %d or greater", threadCount, expectedThreadCount));
242+
}
264243
}
265244

266-
/**
267-
* Waits till the <em>expectedVal</em> equals to the <em>retrievedVal</em>.
268-
* It will report a status message on the first occasion of the value mismatch
269-
* and then, subsequently, when the <em>retrievedVal</em> value changes.
270-
* @param expectedVal The value to wait for
271-
* @param retrievedVal The supplier of the value to check against the <em>expectedVal</em>
272-
* @param msgFormat The formatted message to be printed in case of mismatch
273-
* @param msgArgs The parameters to the formatted message
274-
* @throws InterruptedException
275-
*/
276-
private static void waitTillEquals(long expectedVal, Supplier<Long> retrievedVal,
277-
String msgFormat, Supplier<Object> ... msgArgs)
278-
throws InterruptedException {
279-
Object[] args = null;
280-
281-
long countPrev = -1;
282-
while (true) {
283-
Long count = retrievedVal.get();
284-
if (count == expectedVal) break;
285-
if (countPrev == -1 || countPrev != count) {
286-
if (args == null) {
287-
args = new Object[msgArgs.length];
288-
for(int i=0; i < msgArgs.length; i++) {
289-
args[i] = new ArgWrapper<>((Supplier<Object>)msgArgs[i]);
290-
}
291-
}
292-
System.err.format("TS: %s\n", Instant.now());
293-
System.err.format(
294-
msgFormat
295-
.replace("${provided}", String.valueOf(count))
296-
.replace("$d", "$s"),
297-
args
298-
).flush();
299-
printThreadList();
300-
System.err.println("\nRetrying ...\n");
301-
}
302-
countPrev = count;
303-
Thread.sleep(1);
304-
}
245+
private static long getTestThreadCount() {
246+
return Thread.getAllStackTraces().keySet().stream().filter(
247+
thread -> thread.isAlive() && allThreadIds.contains(thread.getId())).count();
305248
}
306249

307250
private static void updateCounters() {
308251
prevTotalThreadCount = mbean.getTotalStartedThreadCount();
309-
prevLiveThreadCount = mbean.getThreadCount();
252+
prevLiveTestThreadCount = getTestThreadCount();
310253
prevPeakThreadCount = mbean.getPeakThreadCount();
311254
}
312255

0 commit comments

Comments
 (0)