Skip to content

Commit d898b44

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

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

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

+65
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import java.lang.management.ManagementFactory;
2020
import java.lang.management.MemoryMXBean;
2121
import java.lang.management.MemoryUsage;
22+
import java.lang.management.PlatformManagedObject;
2223

2324
/**
2425
* Information about the process of the application.
2526
*
2627
* @author Jonatan Ivanov
28+
* @author Andrey Litvitski
2729
* @since 3.3.0
2830
*/
2931
public class ProcessInfo {
@@ -72,6 +74,29 @@ public MemoryInfo getMemory() {
7274
return new MemoryInfo();
7375
}
7476

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

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

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)