Skip to content

Commit 1f1b9b8

Browse files
committed
Add info contributor support for JDK 24's VirtualThreadSchedulerMXBean
1 parent 681d4c2 commit 1f1b9b8

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/ProcessInfo.java

+64
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Information about the process of the application.
2525
*
2626
* @author Jonatan Ivanov
27+
* @author Andrey Litvitski
2728
* @since 3.3.0
2829
*/
2930
public class ProcessInfo {
@@ -72,6 +73,29 @@ public MemoryInfo getMemory() {
7273
return new MemoryInfo();
7374
}
7475

76+
/**
77+
* Virtual threads information for the process. These values provide details about the
78+
* current state of virtual threads, including the number of mounted threads, queued threads,
79+
* the parallelism level, and the thread pool size.
80+
* @return an instance of {@link VirtualThreadsInfo} containing information about virtual threads,
81+
* or {@code null} if the VirtualThreadSchedulerMXBean is not available.
82+
* @since 3.5.0
83+
*/
84+
public VirtualThreadsInfo getVirtualThreads() {
85+
try {
86+
Class mxBeanClass = Class.forName("jdk.management.VirtualThreadSchedulerMXBean");
87+
Object bean = ManagementFactory.getPlatformMXBean(mxBeanClass);
88+
return new VirtualThreadsInfo(
89+
(Integer) mxBeanClass.getMethod("getMountedVirtualThreadCount").invoke(bean),
90+
(Long) mxBeanClass.getMethod("getQueuedVirtualThreadCount").invoke(bean),
91+
(Integer) mxBeanClass.getMethod("getParallelism").invoke(bean),
92+
(Integer) mxBeanClass.getMethod("getPoolSize").invoke(bean)
93+
);
94+
} catch (ReflectiveOperationException e) {
95+
return null;
96+
}
97+
}
98+
7599
public long getPid() {
76100
return this.pid;
77101
}
@@ -84,6 +108,46 @@ public String getOwner() {
84108
return this.owner;
85109
}
86110

111+
/**
112+
* Virtual threads information.
113+
*
114+
* @since 3.5.0
115+
*/
116+
public static class VirtualThreadsInfo {
117+
118+
private final int mounted;
119+
120+
private final long queued;
121+
122+
private final int parallelism;
123+
124+
private final int poolSize;
125+
126+
public VirtualThreadsInfo(int mounted, long queued, int parallelism, int poolSize) {
127+
this.mounted = mounted;
128+
this.queued = queued;
129+
this.parallelism = parallelism;
130+
this.poolSize = poolSize;
131+
}
132+
133+
public long getMounted() {
134+
return this.mounted;
135+
}
136+
137+
public long getQueued() {
138+
return this.queued;
139+
}
140+
141+
public int getParallelism() {
142+
return this.parallelism;
143+
}
144+
145+
public int getPoolSize() {
146+
return this.poolSize;
147+
}
148+
149+
}
150+
87151
/**
88152
* Memory information.
89153
*

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/ProcessInfoTests.java

+22
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
import org.junit.jupiter.api.Test;
2020

2121
import org.springframework.boot.info.ProcessInfo.MemoryInfo.MemoryUsageInfo;
22+
import org.springframework.boot.info.ProcessInfo.VirtualThreadsInfo;
23+
import org.springframework.util.ClassUtils;
2224

2325
import static org.assertj.core.api.Assertions.assertThat;
2426

2527
/**
2628
* Tests for {@link ProcessInfo}.
2729
*
2830
* @author Jonatan Ivanov
31+
* @author Andrey Litvitski
2932
*/
3033
class ProcessInfoTests {
3134

@@ -54,4 +57,23 @@ void memoryInfoIsAvailable() {
5457
assertThat(nonHeapUsageInfo.getMax()).isEqualTo(-1);
5558
}
5659

60+
@Test
61+
void virtualThreadsInfoIsNullWhenMXBeanIsNotAccessible() {
62+
if (ClassUtils.isPresent("jdk.management.VirtualThreadSchedulerMXBean", null)) {
63+
ProcessInfo processInfo = new ProcessInfo();
64+
65+
VirtualThreadsInfo virtualThreadsInfo = processInfo.getVirtualThreads();
66+
67+
assertThat(virtualThreadsInfo).isNotNull();
68+
assertThat(virtualThreadsInfo.getMounted()).isGreaterThanOrEqualTo(0);
69+
assertThat(virtualThreadsInfo.getQueued()).isGreaterThanOrEqualTo(0);
70+
assertThat(virtualThreadsInfo.getParallelism()).isGreaterThan(0);
71+
assertThat(virtualThreadsInfo.getPoolSize()).isGreaterThan(0);
72+
} else {
73+
ProcessInfo processInfo = new ProcessInfo();
74+
75+
assertThat(processInfo.getVirtualThreads()).isNull();
76+
}
77+
}
78+
5779
}

0 commit comments

Comments
 (0)