Skip to content

Commit 2e9eff5

Browse files
author
Alan Bateman
committed
8309406: Change jdk.trackAllThreads to default to true
Reviewed-by: rpressler, mchung, cjplummer
1 parent 6d155a4 commit 2e9eff5

File tree

6 files changed

+238
-136
lines changed

6 files changed

+238
-136
lines changed

src/java.base/share/classes/jdk/internal/vm/SharedThreadContainer.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2023, 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
@@ -29,7 +29,6 @@
2929
import java.util.Objects;
3030
import java.util.Set;
3131
import java.util.concurrent.ConcurrentHashMap;
32-
import java.util.concurrent.atomic.LongAdder;
3332
import java.util.stream.Stream;
3433
import jdk.internal.access.JavaLangAccess;
3534
import jdk.internal.access.SharedSecrets;
@@ -50,16 +49,13 @@ public class SharedThreadContainer extends ThreadContainer implements AutoClosea
5049
VIRTUAL_THREADS = l.findVarHandle(SharedThreadContainer.class,
5150
"virtualThreads", Set.class);
5251
} catch (Exception e) {
53-
throw new InternalError(e);
52+
throw new ExceptionInInitializerError(e);
5453
}
5554
}
5655

5756
// name of container, used by toString
5857
private final String name;
5958

60-
// the number of threads in the container
61-
private final LongAdder threadCount;
62-
6359
// the virtual threads in the container, created lazily
6460
private volatile Set<Thread> virtualThreads;
6561

@@ -76,7 +72,6 @@ public class SharedThreadContainer extends ThreadContainer implements AutoClosea
7672
private SharedThreadContainer(String name) {
7773
super(/*shared*/ true);
7874
this.name = name;
79-
this.threadCount = new LongAdder();
8075
}
8176

8277
/**
@@ -119,21 +114,14 @@ public void onStart(Thread thread) {
119114
}
120115
vthreads.add(thread);
121116
}
122-
threadCount.add(1L);
123117
}
124118

125119
@Override
126120
public void onExit(Thread thread) {
127-
threadCount.add(-1L);
128121
if (thread.isVirtual())
129122
virtualThreads.remove(thread);
130123
}
131124

132-
@Override
133-
public long threadCount() {
134-
return threadCount.sum();
135-
}
136-
137125
@Override
138126
public Stream<Thread> threads() {
139127
// live platform threads in this container

src/java.base/share/classes/jdk/internal/vm/ThreadContainers.java

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,35 @@
3333
import java.util.stream.Stream;
3434
import jdk.internal.access.JavaLangAccess;
3535
import jdk.internal.access.SharedSecrets;
36-
import sun.nio.ch.Poller;
3736
import sun.security.action.GetPropertyAction;
3837

3938
/**
40-
* This class consists exclusively of static methods to support debugging and
41-
* monitoring of threads.
39+
* This class consists exclusively of static methods to support groupings of threads.
4240
*/
4341
public class ThreadContainers {
4442
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
4543

44+
// true if all threads are tracked
45+
private static final boolean TRACK_ALL_THREADS;
46+
47+
// the root container
48+
private static final RootContainer ROOT_CONTAINER;
49+
4650
// the set of thread containers registered with this class
4751
private static final Set<WeakReference<ThreadContainer>> CONTAINER_REGISTRY = ConcurrentHashMap.newKeySet();
4852
private static final ReferenceQueue<Object> QUEUE = new ReferenceQueue<>();
4953

54+
static {
55+
String s = GetPropertyAction.privilegedGetProperty("jdk.trackAllThreads");
56+
if (s == null || s.isEmpty() || Boolean.parseBoolean(s)) {
57+
TRACK_ALL_THREADS = true;
58+
ROOT_CONTAINER = new RootContainer.TrackingRootContainer();
59+
} else {
60+
TRACK_ALL_THREADS = false;
61+
ROOT_CONTAINER = new RootContainer.CountingRootContainer();
62+
}
63+
}
64+
5065
private ThreadContainers() { }
5166

5267
/**
@@ -59,6 +74,13 @@ private static void expungeStaleEntries() {
5974
}
6075
}
6176

77+
/**
78+
* Returns true if all threads are tracked.
79+
*/
80+
public static boolean trackAllThreads() {
81+
return TRACK_ALL_THREADS;
82+
}
83+
6284
/**
6385
* Registers a thread container to be tracked this class, returning a key
6486
* that is used to remove it from the registry.
@@ -83,7 +105,7 @@ public static void deregisterContainer(Object key) {
83105
* Returns the root thread container.
84106
*/
85107
public static ThreadContainer root() {
86-
return RootContainer.INSTANCE;
108+
return ROOT_CONTAINER;
87109
}
88110

89111
/**
@@ -183,20 +205,10 @@ private static ThreadContainer next(ThreadContainer container) {
183205
}
184206

185207
/**
186-
* Root container that "contains" all platform threads not started in a
187-
* container plus some (or all) virtual threads that are started directly
188-
* with the Thread API.
208+
* Root container that "contains" all platform threads not started in a container.
209+
* It may include all virtual threads started directly with the Thread API.
189210
*/
190211
private static abstract class RootContainer extends ThreadContainer {
191-
static final RootContainer INSTANCE;
192-
static {
193-
String s = GetPropertyAction.privilegedGetProperty("jdk.trackAllThreads");
194-
if (s != null && (s.isEmpty() || Boolean.parseBoolean(s))) {
195-
INSTANCE = new TrackingRootContainer();
196-
} else {
197-
INSTANCE = new CountingRootContainer();
198-
}
199-
}
200212
protected RootContainer() {
201213
super(true);
202214
}
@@ -270,11 +282,7 @@ public long threadCount() {
270282
}
271283
@Override
272284
public Stream<Thread> threads() {
273-
// virtual threads in this container that are those blocked on I/O.
274-
Stream<Thread> blockedVirtualThreads = Poller.blockedThreads()
275-
.filter(t -> t.isVirtual()
276-
&& JLA.threadContainer(t) == this);
277-
return Stream.concat(platformThreads(), blockedVirtualThreads);
285+
return platformThreads();
278286
}
279287
}
280288
}

src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2023, 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
@@ -240,7 +240,9 @@ private static void dumpThreadsToJson(ThreadContainer container,
240240
out.println(" ],"); // end of threads
241241

242242
// thread count
243-
threadCount = Long.max(threadCount, container.threadCount());
243+
if (!ThreadContainers.trackAllThreads()) {
244+
threadCount = Long.max(threadCount, container.threadCount());
245+
}
244246
out.format(" \"threadCount\": \"%d\"%n", threadCount);
245247

246248
if (more) {

test/hotspot/jtreg/serviceability/dcmd/thread/ThreadDumpToFileTest.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void testPlainThreadDump() throws IOException {
6666
@Test
6767
void testJsonThreadDump() throws IOException {
6868
Path file = genThreadDumpPath(".json");
69-
threadDump(file, "-format=json").shouldMatch("Created");
69+
jcmdThreadDumpToFile(file, "-format=json").shouldMatch("Created");
7070

7171
// parse the JSON text
7272
String jsonText = Files.readString(file);
@@ -89,7 +89,7 @@ void testDoNotOverwriteFile() throws IOException {
8989
Path file = genThreadDumpPath(".txt");
9090
Files.writeString(file, "xxx");
9191

92-
threadDump(file, "").shouldMatch("exists");
92+
jcmdThreadDumpToFile(file, "").shouldMatch("exists");
9393

9494
// file should not be overridden
9595
assertEquals("xxx", Files.readString(file));
@@ -102,14 +102,14 @@ void testDoNotOverwriteFile() throws IOException {
102102
void testOverwriteFile() throws IOException {
103103
Path file = genThreadDumpPath(".txt");
104104
Files.writeString(file, "xxx");
105-
testPlainThreadDump(file, "-overwrite");
105+
jcmdThreadDumpToFile(file, "-overwrite");
106106
}
107107

108108
/**
109109
* Test thread dump in plain text format.
110110
*/
111111
private void testPlainThreadDump(Path file, String... options) throws IOException {
112-
threadDump(file, options).shouldMatch("Created");
112+
jcmdThreadDumpToFile(file, options).shouldMatch("Created");
113113

114114
// test that thread dump contains the name and id of the current thread
115115
String name = Thread.currentThread().getName();
@@ -118,21 +118,30 @@ private void testPlainThreadDump(Path file, String... options) throws IOExceptio
118118
assertTrue(find(file, expected), expected + " not found in " + file);
119119
}
120120

121+
/**
122+
* Generate a file path with the given suffix to use for the thread dump.
123+
*/
121124
private Path genThreadDumpPath(String suffix) throws IOException {
122125
Path dir = Path.of(".").toAbsolutePath();
123126
Path file = Files.createTempFile(dir, "threads-", suffix);
124127
Files.delete(file);
125128
return file;
126129
}
127130

128-
private OutputAnalyzer threadDump(Path file, String... options) {
131+
/**
132+
* Launches jcmd Thread.dump_to_file to obtain a thread dump of this VM.
133+
*/
134+
private OutputAnalyzer jcmdThreadDumpToFile(Path file, String... options) {
129135
String cmd = "Thread.dump_to_file";
130136
for (String option : options) {
131137
cmd += " " + option;
132138
}
133139
return new PidJcmdExecutor().execute(cmd + " " + file);
134140
}
135141

142+
/**
143+
* Returns true if the given file contains a line with the string.
144+
*/
136145
private boolean find(Path file, String text) throws IOException {
137146
try (Stream<String> stream = Files.lines(file)) {
138147
return stream.anyMatch(line -> line.indexOf(text) >= 0);

0 commit comments

Comments
 (0)