From 1c61ab1d96074e4ee1bb40accb230e1c9fdfebf4 Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Mon, 13 Jan 2025 14:35:49 +0200 Subject: [PATCH] Polish ProcessInfo Signed-off-by: Dmytro Nosan --- .../boot/info/ProcessInfo.java | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/ProcessInfo.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/ProcessInfo.java index 3d3d7aedda3a..792b9c18820c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/ProcessInfo.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/ProcessInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,9 @@ import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.lang.management.PlatformManagedObject; +import java.lang.reflect.Method; + +import org.springframework.util.ClassUtils; /** * Information about the process of the application. @@ -30,6 +33,11 @@ */ public class ProcessInfo { + private static final String VIRTUAL_THREAD_SCHEDULER_CLASS = "jdk.management.VirtualThreadSchedulerMXBean"; + + private static final boolean VIRTUAL_THREAD_SCHEDULER_CLASS_PRESENT = ClassUtils + .isPresent(VIRTUAL_THREAD_SCHEDULER_CLASS, null); + private static final Runtime runtime = Runtime.getRuntime(); private final long pid; @@ -85,14 +93,18 @@ public MemoryInfo getMemory() { */ @SuppressWarnings("unchecked") public VirtualThreadsInfo getVirtualThreads() { + if (!VIRTUAL_THREAD_SCHEDULER_CLASS_PRESENT) { + return null; + } try { - Class mxBeanClass = (Class) 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)); + Class mxbeanClass = (Class) ClassUtils + .forName(VIRTUAL_THREAD_SCHEDULER_CLASS, null); + PlatformManagedObject mxbean = ManagementFactory.getPlatformMXBean(mxbeanClass); + int mountedVirtualThreadCount = invokeMethod(mxbeanClass, mxbean, "getMountedVirtualThreadCount"); + long queuedVirtualThreadCount = invokeMethod(mxbeanClass, mxbean, "getQueuedVirtualThreadCount"); + int parallelism = invokeMethod(mxbeanClass, mxbean, "getParallelism"); + int poolSize = invokeMethod(mxbeanClass, mxbean, "getPoolSize"); + return new VirtualThreadsInfo(mountedVirtualThreadCount, queuedVirtualThreadCount, parallelism, poolSize); } catch (ReflectiveOperationException ex) { return null; @@ -111,6 +123,12 @@ public String getOwner() { return this.owner; } + @SuppressWarnings("unchecked") + private T invokeMethod(Class mxbeanClass, Object mxbean, String name) throws ReflectiveOperationException { + Method method = mxbeanClass.getMethod(name); + return (T) method.invoke(mxbean); + } + /** * Virtual threads information. * @@ -126,7 +144,7 @@ public static class VirtualThreadsInfo { private final int poolSize; - public VirtualThreadsInfo(int mounted, long queued, int parallelism, int poolSize) { + VirtualThreadsInfo(int mounted, long queued, int parallelism, int poolSize) { this.mounted = mounted; this.queued = queued; this.parallelism = parallelism;