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 8961643699f8..c6c16e97b0fd 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 @@ -16,11 +16,13 @@ package org.springframework.boot.info; +import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.lang.management.PlatformManagedObject; import java.lang.reflect.Method; +import java.util.List; import org.springframework.util.ClassUtils; @@ -178,13 +180,19 @@ public static class MemoryInfo { private static final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + private static final List garbageCollectorMXBeans = ManagementFactory + .getGarbageCollectorMXBeans(); + private final MemoryUsageInfo heap; private final MemoryUsageInfo nonHeap; + private final List garbageCollectors; + MemoryInfo() { this.heap = new MemoryUsageInfo(memoryMXBean.getHeapMemoryUsage()); this.nonHeap = new MemoryUsageInfo(memoryMXBean.getNonHeapMemoryUsage()); + this.garbageCollectors = garbageCollectorMXBeans.stream().map(GarbageCollectorInfo::new).toList(); } public MemoryUsageInfo getHeap() { @@ -195,6 +203,20 @@ public MemoryUsageInfo getNonHeap() { return this.nonHeap; } + /** + * Garbage Collector information for the process. This list provides details about + * the currently used GC algorithms selected by the user or JVM ergonomics. It + * might not be trivial to know the used GC algorithms since that usually depends + * on the {@link Runtime#availableProcessors()} (see: + * {@link ProcessInfo#getCpus()}) and the available memory (see: + * {@link MemoryUsageInfo}). + * @return {@link List} of {@link GarbageCollectorInfo}. + * @since 3.5.0 + */ + public List getGarbageCollectors() { + return this.garbageCollectors; + } + public static class MemoryUsageInfo { private final MemoryUsage memoryUsage; @@ -221,6 +243,27 @@ public long getMax() { } + public static class GarbageCollectorInfo { + + private final String name; + + private final long collectionCount; + + GarbageCollectorInfo(GarbageCollectorMXBean garbageCollectorMXBean) { + this.name = garbageCollectorMXBean.getName(); + this.collectionCount = garbageCollectorMXBean.getCollectionCount(); + } + + public String getName() { + return this.name; + } + + public long getCollectionCount() { + return this.collectionCount; + } + + } + } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/ProcessInfoTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/ProcessInfoTests.java index ed6acfa2cb32..d0df5320dc3c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/ProcessInfoTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/ProcessInfoTests.java @@ -16,10 +16,13 @@ package org.springframework.boot.info; +import java.util.List; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; +import org.springframework.boot.info.ProcessInfo.MemoryInfo; import org.springframework.boot.info.ProcessInfo.MemoryInfo.MemoryUsageInfo; import org.springframework.boot.info.ProcessInfo.VirtualThreadsInfo; @@ -56,6 +59,12 @@ void memoryInfoIsAvailable() { assertThat(nonHeapUsageInfo.getUsed()).isPositive().isLessThanOrEqualTo(nonHeapUsageInfo.getCommitted()); assertThat(nonHeapUsageInfo.getCommitted()).isPositive(); assertThat(nonHeapUsageInfo.getMax()).isEqualTo(-1); + List garbageCollectors = processInfo.getMemory().getGarbageCollectors(); + assertThat(garbageCollectors).isNotEmpty(); + assertThat(garbageCollectors).allSatisfy((garbageCollector) -> { + assertThat(garbageCollector.getName()).isNotEmpty(); + assertThat(garbageCollector.getCollectionCount()).isNotNegative(); + }); } @Test