Add info contributor support for JDK 24's VirtualThreadSchedulerMXBean

See gh-43594
This commit is contained in:
Andrey Litvitski
2024-12-25 22:00:05 +03:00
committed by Moritz Halbritter
parent b41fc55e23
commit 104397fb91
2 changed files with 86 additions and 0 deletions
@@ -24,6 +24,7 @@ import java.lang.management.MemoryUsage;
* Information about the process of the application.
*
* @author Jonatan Ivanov
* @author Andrey Litvitski
* @since 3.3.0
*/
public class ProcessInfo {
@@ -72,6 +73,29 @@ public class ProcessInfo {
return new MemoryInfo();
}
/**
* Virtual threads information for the process. These values provide details about the
* current state of virtual threads, including the number of mounted threads, queued threads,
* the parallelism level, and the thread pool size.
* @return an instance of {@link VirtualThreadsInfo} containing information about virtual threads,
* or {@code null} if the VirtualThreadSchedulerMXBean is not available.
* @since 3.5.0
*/
public VirtualThreadsInfo getVirtualThreads() {
try {
Class mxBeanClass = Class.forName("jdk.management.VirtualThreadSchedulerMXBean");
Object bean = ManagementFactory.getPlatformMXBean(mxBeanClass);
return new VirtualThreadsInfo(
(Integer) mxBeanClass.getMethod("getMountedVirtualThreadCount").invoke(bean),
(Long) mxBeanClass.getMethod("getQueuedVirtualThreadCount").invoke(bean),
(Integer) mxBeanClass.getMethod("getParallelism").invoke(bean),
(Integer) mxBeanClass.getMethod("getPoolSize").invoke(bean)
);
} catch (ReflectiveOperationException e) {
return null;
}
}
public long getPid() {
return this.pid;
}
@@ -84,6 +108,46 @@ public class ProcessInfo {
return this.owner;
}
/**
* Virtual threads information.
*
* @since 3.5.0
*/
public static class VirtualThreadsInfo {
private final int mounted;
private final long queued;
private final int parallelism;
private final int poolSize;
public VirtualThreadsInfo(int mounted, long queued, int parallelism, int poolSize) {
this.mounted = mounted;
this.queued = queued;
this.parallelism = parallelism;
this.poolSize = poolSize;
}
public long getMounted() {
return this.mounted;
}
public long getQueued() {
return this.queued;
}
public int getParallelism() {
return this.parallelism;
}
public int getPoolSize() {
return this.poolSize;
}
}
/**
* Memory information.
*
@@ -19,6 +19,8 @@ package org.springframework.boot.info;
import org.junit.jupiter.api.Test;
import org.springframework.boot.info.ProcessInfo.MemoryInfo.MemoryUsageInfo;
import org.springframework.boot.info.ProcessInfo.VirtualThreadsInfo;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -26,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ProcessInfo}.
*
* @author Jonatan Ivanov
* @author Andrey Litvitski
*/
class ProcessInfoTests {
@@ -54,4 +57,23 @@ class ProcessInfoTests {
assertThat(nonHeapUsageInfo.getMax()).isEqualTo(-1);
}
@Test
void virtualThreadsInfoIsNullWhenMXBeanIsNotAccessible() {
if (ClassUtils.isPresent("jdk.management.VirtualThreadSchedulerMXBean", null)) {
ProcessInfo processInfo = new ProcessInfo();
VirtualThreadsInfo virtualThreadsInfo = processInfo.getVirtualThreads();
assertThat(virtualThreadsInfo).isNotNull();
assertThat(virtualThreadsInfo.getMounted()).isGreaterThanOrEqualTo(0);
assertThat(virtualThreadsInfo.getQueued()).isGreaterThanOrEqualTo(0);
assertThat(virtualThreadsInfo.getParallelism()).isGreaterThan(0);
assertThat(virtualThreadsInfo.getPoolSize()).isGreaterThan(0);
} else {
ProcessInfo processInfo = new ProcessInfo();
assertThat(processInfo.getVirtualThreads()).isNull();
}
}
}