1
1
/*
2
- * Copyright (c) 2004, 2021 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2004, 2023 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
30
30
* @run main/othervm ThreadLists
31
31
*/
32
32
import java .lang .management .ManagementFactory ;
33
+ import java .lang .management .ThreadInfo ;
33
34
import java .lang .management .ThreadMXBean ;
34
35
import java .util .Map ;
36
+ import java .util .Set ;
37
+ import java .util .TreeSet ;
35
38
36
39
public class ThreadLists {
40
+
41
+ // Thread names permitted to appear during test:
42
+ public static final String [] permittedThreadNames = { "ForkJoinPool" , "JVMCI" };
43
+
44
+ public static boolean isPermittedNewThread (String name ) {
45
+ for (String s : permittedThreadNames ) {
46
+ if (name .contains (s )) {
47
+ return true ;
48
+ }
49
+ }
50
+ return false ;
51
+ }
52
+
37
53
public static void main (String args []) {
38
54
39
55
// Bug id : JDK-8151797
@@ -50,44 +66,81 @@ public static void main(String args[]) {
50
66
} while (parent != null );
51
67
52
68
// get the thread count
53
- int activeCount = top .activeCount ();
69
+ int tgActiveCount = top .activeCount ();
54
70
55
71
// Now enumerate to see if we find any extras yet.
56
- // Ensure the array is big enough for a few extras.
57
- Thread [] threads = new Thread [activeCount * 2 ];
58
- int newCount = top .enumerate (threads );
59
- if (newCount != activeCount ) {
60
- System .out .println ("Found different threads after enumeration:" );
61
- } else {
62
- System .out .println ("Initial set of enumerated threads:" );
72
+ // Ensure array is big enough for a few extras.
73
+ Thread [] tgThreads = new Thread [tgActiveCount * 2 ];
74
+ int tgNewCount = top .enumerate (tgThreads );
75
+ Map <Thread , StackTraceElement []> stackTraces = Thread .getAllStackTraces ();
76
+
77
+ if (tgNewCount != tgActiveCount ) {
78
+ System .out .println ("Found different Thread Group thread count after enumeration: tgActiveCount="
79
+ + tgActiveCount + " enumerated=" + tgNewCount );
63
80
}
64
- for (int i = 0 ; i < newCount ; i ++) {
65
- System .out .println (" - Thread: " + threads [i ].getName ());
81
+ if (tgNewCount != stackTraces .size ()) {
82
+ System .out .println ("Found difference in counts: thread group new count="
83
+ + tgNewCount + " stackTraces.size()=" + stackTraces .size ());
84
+ }
85
+ System .out .println ("Initial set of enumerated threads:" );
86
+ for (int i = 0 ; i < tgNewCount ; i ++) {
87
+ System .out .println (" - Thread: " + tgThreads [i ].getName ());
66
88
}
67
89
68
- Map <Thread , StackTraceElement []> stackTraces = Thread .getAllStackTraces ();
69
-
90
+ // Get Threads from MXBean. Retry to ensure count and id count match.
70
91
ThreadMXBean threadBean = ManagementFactory .getThreadMXBean ();
71
- int threadCount = threadBean .getThreadCount ();
72
- long [] threadIds = threadBean .getAllThreadIds ();
92
+ int threadCountBean = 0 ;
93
+ long [] threadIdsBean = null ;
94
+ do {
95
+ System .out .println ("Gathering Thread info from MXBean..." );
96
+ threadCountBean = threadBean .getThreadCount ();
97
+ threadIdsBean = threadBean .getAllThreadIds ();
98
+ } while (threadCountBean != threadIdsBean .length );
73
99
74
- System .out .println ("ThreadGroup: " + activeCount + " active thread(s)" );
75
- System .out .println ("Thread: " + stackTraces .size () + " stack trace(s) returned" );
76
- System .out .println ("ThreadMXBean: " + threadCount + " live threads(s)" );
77
- System .out .println ("ThreadMXBean: " + threadIds .length + " thread Id(s)" );
100
+ System .out .println ("ThreadGroup: " + tgActiveCount + " active thread(s)" );
101
+ System .out .println ("Thread.getAllStackTraces: " + stackTraces .size () + " stack trace(s) returned" );
102
+ System .out .println ("ThreadMXBean: " + threadCountBean + " live threads(s)" );
103
+ System .out .println ("ThreadMXBean: " + threadIdsBean .length + " thread Id(s)" );
104
+
105
+ if (threadIdsBean .length > tgActiveCount ) {
106
+ // Find the new Threads: some Thead names are permitted to appear: ignore them.
107
+ Set <Long > seenTids = new TreeSet <>();
108
+ for (Thread t : stackTraces .keySet ()) {
109
+ if (t != null ) {
110
+ seenTids .add (t .getId ());
111
+ }
112
+ }
113
+ for (long tid : threadIdsBean ) {
114
+ if (!seenTids .contains (tid )) {
115
+ // New Thread from MBean, compared to Thread Group:
116
+ ThreadInfo threadInfo = threadBean .getThreadInfo (tid );
117
+ if (threadInfo != null && isPermittedNewThread (threadInfo .getThreadName ())) {
118
+ System .out .print ("New thread permitted: " + threadInfo );
119
+ threadCountBean --;
120
+ }
121
+ }
122
+ }
123
+ }
78
124
79
125
// check results are consistent
80
126
boolean failed = false ;
81
- if (activeCount != stackTraces .size ()) failed = true ;
82
- if (activeCount != threadCount ) failed = true ;
83
- if ( activeCount != threadIds . length ) failed = true ;
127
+ if (tgActiveCount != stackTraces .size ()) failed = true ;
128
+ if (tgActiveCount != threadCountBean ) failed = true ;
129
+ // We know threadCountBean == threadIdsBean.length
84
130
85
131
if (failed ) {
86
- System .out .println ("Set of stack-traced threads:" );
132
+ System .out .println ("Failed." );
133
+ System .out .println ("Set of Threads from getAllStackTraces:" );
87
134
for (Thread t : stackTraces .keySet ()) {
88
135
System .out .println (" - Thread: " +
89
136
(t != null ? t .getName () : "null!" ));
90
137
}
138
+ System .out .println ("Set of Thread IDs from MXBean:" );
139
+ for (long tid : threadIdsBean ) {
140
+ System .out .print (tid + " " );
141
+ ThreadInfo threadInfo = threadBean .getThreadInfo (tid );
142
+ System .out .println (threadInfo != null ? threadInfo .getThreadName () : "" );
143
+ }
91
144
throw new RuntimeException ("inconsistent results" );
92
145
}
93
146
}
0 commit comments