Skip to content

Commit 7e2bcf6

Browse files
author
Alan Bateman
committedSep 10, 2024
8338890: Add monitoring/management interface for the virtual thread scheduler
Reviewed-by: kevinw
1 parent 5e822c2 commit 7e2bcf6

File tree

23 files changed

+711
-53
lines changed

23 files changed

+711
-53
lines changed
 

‎src/java.base/share/classes/java/lang/System.java

+5
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import java.util.ResourceBundle;
6666
import java.util.Set;
6767
import java.util.WeakHashMap;
68+
import java.util.concurrent.Executor;
6869
import java.util.function.Supplier;
6970
import java.util.concurrent.ConcurrentHashMap;
7071
import java.util.stream.Stream;
@@ -2766,6 +2767,10 @@ public void unparkVirtualThread(Thread thread) {
27662767
}
27672768
}
27682769

2770+
public Executor virtualThreadDefaultScheduler() {
2771+
return VirtualThread.defaultScheduler();
2772+
}
2773+
27692774
public StackWalker newStackWalkerInstance(Set<StackWalker.Option> options,
27702775
ContinuationScope contScope,
27712776
Continuation continuation) {

‎src/java.base/share/classes/java/lang/VirtualThread.java

+8
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ final class VirtualThread extends BaseVirtualThread {
142142
// termination object when joining, created lazily if needed
143143
private volatile CountDownLatch termination;
144144

145+
146+
/**
147+
* Returns the default scheduler.
148+
*/
149+
static Executor defaultScheduler() {
150+
return DEFAULT_SCHEDULER;
151+
}
152+
145153
/**
146154
* Returns the continuation scope used for virtual threads.
147155
*/

‎src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.Map;
4545
import java.util.Set;
4646
import java.util.concurrent.ConcurrentHashMap;
47+
import java.util.concurrent.Executor;
4748
import java.util.concurrent.RejectedExecutionException;
4849
import java.util.stream.Stream;
4950

@@ -601,6 +602,11 @@ public interface JavaLangAccess {
601602
*/
602603
void unparkVirtualThread(Thread thread);
603604

605+
/**
606+
* Returns the virtual thread default scheduler.
607+
*/
608+
Executor virtualThreadDefaultScheduler();
609+
604610
/**
605611
* Creates a new StackWalker
606612
*/

‎src/java.base/share/classes/module-info.java

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
jdk.jartool,
173173
jdk.jlink,
174174
jdk.jfr,
175+
jdk.management,
175176
jdk.net,
176177
jdk.sctp,
177178
jdk.crypto.cryptoki;

‎src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2024, 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
@@ -41,6 +41,7 @@
4141
import java.util.stream.Collectors;
4242
import java.util.stream.Stream;
4343
import javax.management.DynamicMBean;
44+
import jdk.management.VirtualThreadSchedulerMXBean;
4445
import sun.management.ManagementFactoryHelper;
4546
import sun.management.spi.PlatformMBeanProvider;
4647

@@ -163,6 +164,41 @@ public synchronized Map<String, java.lang.management.ThreadMXBean> nameToMBeanMa
163164
}
164165
});
165166

167+
/**
168+
* VirtualThreadSchedulerMXBean.
169+
*/
170+
initMBeanList.add(new PlatformComponent<VirtualThreadSchedulerMXBean>() {
171+
private final Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces =
172+
Set.of(VirtualThreadSchedulerMXBean.class);
173+
private final Set<String> mbeanInterfaceNames =
174+
Set.of(VirtualThreadSchedulerMXBean.class.getName());
175+
private VirtualThreadSchedulerMXBean impl;
176+
177+
@Override
178+
public Set<Class<? extends VirtualThreadSchedulerMXBean>> mbeanInterfaces() {
179+
return mbeanInterfaces;
180+
}
181+
182+
@Override
183+
public Set<String> mbeanInterfaceNames() {
184+
return mbeanInterfaceNames;
185+
}
186+
187+
@Override
188+
public String getObjectNamePattern() {
189+
return "jdk.management:type=VirtualThreadScheduler";
190+
}
191+
192+
@Override
193+
public Map<String, VirtualThreadSchedulerMXBean> nameToMBeanMap() {
194+
VirtualThreadSchedulerMXBean impl = this.impl;
195+
if (impl == null) {
196+
this.impl = impl = VirtualThreadSchedulerImpls.create();
197+
}
198+
return Map.of("jdk.management:type=VirtualThreadScheduler", impl);
199+
}
200+
});
201+
166202
/**
167203
* OperatingSystemMXBean
168204
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.sun.management.internal;
26+
27+
import java.util.concurrent.Executor;
28+
import java.util.concurrent.ForkJoinPool;
29+
import javax.management.ObjectName;
30+
import jdk.management.VirtualThreadSchedulerMXBean;
31+
import jdk.internal.access.JavaLangAccess;
32+
import jdk.internal.access.SharedSecrets;
33+
import jdk.internal.vm.ContinuationSupport;
34+
import sun.management.Util;
35+
36+
/**
37+
* Provides the implementation of the management interface for the JDK's default virtual
38+
* thread scheduler.
39+
*/
40+
public class VirtualThreadSchedulerImpls {
41+
private VirtualThreadSchedulerImpls() {
42+
}
43+
44+
public static VirtualThreadSchedulerMXBean create() {
45+
if (ContinuationSupport.isSupported()) {
46+
return new VirtualThreadSchedulerImpl();
47+
} else {
48+
return new BoundVirtualThreadSchedulerImpl();
49+
}
50+
}
51+
52+
/**
53+
* Base implementation of VirtualThreadSchedulerMXBean.
54+
*/
55+
private abstract static class BaseVirtualThreadSchedulerImpl
56+
implements VirtualThreadSchedulerMXBean {
57+
58+
abstract void implSetParallelism(int size);
59+
60+
@Override
61+
public final void setParallelism(int size) {
62+
Util.checkControlAccess();
63+
implSetParallelism(size);
64+
}
65+
66+
@Override
67+
public final ObjectName getObjectName() {
68+
return Util.newObjectName("jdk.management:type=VirtualThreadScheduler");
69+
}
70+
71+
@Override
72+
public String toString() {
73+
var sb = new StringBuilder("[parallelism=");
74+
sb.append(getParallelism());
75+
append(sb, "size", getPoolSize());
76+
append(sb, "mounted", getMountedVirtualThreadCount());
77+
append(sb, "queued", getQueuedVirtualThreadCount());
78+
sb.append(']');
79+
return sb.toString();
80+
}
81+
82+
private void append(StringBuilder sb, String name, long value) {
83+
sb.append(", ").append(name).append('=');
84+
if (value >= 0) {
85+
sb.append(value);
86+
} else {
87+
sb.append("<unavailable>");
88+
}
89+
}
90+
}
91+
92+
/**
93+
* Implementation of VirtualThreadSchedulerMXBean when virtual threads are
94+
* implemented with continuations + scheduler.
95+
*/
96+
private static final class VirtualThreadSchedulerImpl extends BaseVirtualThreadSchedulerImpl {
97+
/**
98+
* Holder class for scheduler.
99+
*/
100+
private static class Scheduler {
101+
private static final Executor scheduler =
102+
SharedSecrets.getJavaLangAccess().virtualThreadDefaultScheduler();
103+
static Executor instance() {
104+
return scheduler;
105+
}
106+
}
107+
108+
@Override
109+
public int getParallelism() {
110+
if (Scheduler.instance() instanceof ForkJoinPool pool) {
111+
return pool.getParallelism();
112+
}
113+
throw new InternalError(); // should not get here
114+
}
115+
116+
@Override
117+
void implSetParallelism(int size) {
118+
if (Scheduler.instance() instanceof ForkJoinPool pool) {
119+
pool.setParallelism(size);
120+
if (pool.getPoolSize() < size) {
121+
// FJ worker thread creation is on-demand
122+
Thread.startVirtualThread(() -> { });
123+
}
124+
125+
return;
126+
}
127+
throw new UnsupportedOperationException(); // should not get here
128+
}
129+
130+
@Override
131+
public int getPoolSize() {
132+
if (Scheduler.instance() instanceof ForkJoinPool pool) {
133+
return pool.getPoolSize();
134+
}
135+
return -1; // should not get here
136+
}
137+
138+
@Override
139+
public int getMountedVirtualThreadCount() {
140+
if (Scheduler.instance() instanceof ForkJoinPool pool) {
141+
return pool.getActiveThreadCount();
142+
}
143+
return -1; // should not get here
144+
}
145+
146+
@Override
147+
public long getQueuedVirtualThreadCount() {
148+
if (Scheduler.instance() instanceof ForkJoinPool pool) {
149+
return pool.getQueuedTaskCount() + pool.getQueuedSubmissionCount();
150+
}
151+
return -1L; // should not get here
152+
}
153+
}
154+
155+
/**
156+
* Implementation of VirtualThreadSchedulerMXBean when virtual threads are backed
157+
* by platform threads.
158+
*/
159+
private static final class BoundVirtualThreadSchedulerImpl extends BaseVirtualThreadSchedulerImpl {
160+
@Override
161+
public int getParallelism() {
162+
return Integer.MAX_VALUE;
163+
}
164+
165+
@Override
166+
void implSetParallelism(int size) {
167+
throw new UnsupportedOperationException();
168+
}
169+
170+
@Override
171+
public int getPoolSize() {
172+
return -1;
173+
}
174+
175+
@Override
176+
public int getMountedVirtualThreadCount() {
177+
return -1;
178+
}
179+
180+
@Override
181+
public long getQueuedVirtualThreadCount() {
182+
return -1L;
183+
}
184+
}
185+
}

‎src/jdk.management/share/classes/com/sun/management/package-info.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2024, 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
@@ -24,9 +24,8 @@
2424
*/
2525

2626
/**
27-
* This package contains the JDK's extension to
28-
* the standard implementation of the
29-
* {@link java.lang.management} API and also defines the management
27+
* This package contains JDK extensions to the standard implementation of
28+
* the {@link java.lang.management} API and also defines the management
3029
* interface for some other components of the platform.
3130
*
3231
* <p>

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Sep 10, 2024

@openjdk-notifier[bot]
Please sign in to comment.