Skip to content

Commit 01cdd69

Browse files
committed
Merge pull request #43594 from panic08
* pr/43594: Polish "Add info contributor support for JDK 24's VirtualThreadSchedulerMXBean" Add info contributor support for JDK 24's VirtualThreadSchedulerMXBean Closes gh-43594
2 parents b41fc55 + 821af70 commit 01cdd69

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

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

+67
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,31 @@ 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
80+
* threads, the parallelism level, and the thread pool size.
81+
* @return an instance of {@link VirtualThreadsInfo} containing information about
82+
* virtual threads, or {@code null} if the VirtualThreadSchedulerMXBean is not
83+
* available.
84+
* @since 3.5.0
85+
*/
86+
@SuppressWarnings("unchecked")
87+
public VirtualThreadsInfo getVirtualThreads() {
88+
try {
89+
Class<PlatformManagedObject> mxBeanClass = (Class<PlatformManagedObject>) Class
90+
.forName("jdk.management.VirtualThreadSchedulerMXBean");
91+
Object bean = ManagementFactory.getPlatformMXBean(mxBeanClass);
92+
return new VirtualThreadsInfo((Integer) mxBeanClass.getMethod("getMountedVirtualThreadCount").invoke(bean),
93+
(Long) mxBeanClass.getMethod("getQueuedVirtualThreadCount").invoke(bean),
94+
(Integer) mxBeanClass.getMethod("getParallelism").invoke(bean),
95+
(Integer) mxBeanClass.getMethod("getPoolSize").invoke(bean));
96+
}
97+
catch (ReflectiveOperationException ex) {
98+
return null;
99+
}
100+
}
101+
75102
public long getPid() {
76103
return this.pid;
77104
}
@@ -84,6 +111,46 @@ public String getOwner() {
84111
return this.owner;
85112
}
86113

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

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

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,15 +17,19 @@
1717
package org.springframework.boot.info;
1818

1919
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.condition.EnabledForJreRange;
21+
import org.junit.jupiter.api.condition.JRE;
2022

2123
import org.springframework.boot.info.ProcessInfo.MemoryInfo.MemoryUsageInfo;
24+
import org.springframework.boot.info.ProcessInfo.VirtualThreadsInfo;
2225

2326
import static org.assertj.core.api.Assertions.assertThat;
2427

2528
/**
2629
* Tests for {@link ProcessInfo}.
2730
*
2831
* @author Jonatan Ivanov
32+
* @author Andrey Litvitski
2933
*/
3034
class ProcessInfoTests {
3135

@@ -54,4 +58,23 @@ void memoryInfoIsAvailable() {
5458
assertThat(nonHeapUsageInfo.getMax()).isEqualTo(-1);
5559
}
5660

61+
@Test
62+
@EnabledForJreRange(min = JRE.JAVA_24)
63+
void virtualThreadsInfoIfAvailable() {
64+
ProcessInfo processInfo = new ProcessInfo();
65+
VirtualThreadsInfo virtualThreadsInfo = processInfo.getVirtualThreads();
66+
assertThat(virtualThreadsInfo).isNotNull();
67+
assertThat(virtualThreadsInfo.getMounted()).isGreaterThanOrEqualTo(0);
68+
assertThat(virtualThreadsInfo.getQueued()).isGreaterThanOrEqualTo(0);
69+
assertThat(virtualThreadsInfo.getParallelism()).isGreaterThan(0);
70+
assertThat(virtualThreadsInfo.getPoolSize()).isGreaterThanOrEqualTo(0);
71+
}
72+
73+
@Test
74+
@EnabledForJreRange(max = JRE.JAVA_23)
75+
void virtualThreadsInfoIfNotAvailable() {
76+
ProcessInfo processInfo = new ProcessInfo();
77+
assertThat(processInfo.getVirtualThreads()).isNull();
78+
}
79+
5780
}

0 commit comments

Comments
 (0)