Merge pull request #44704 from jonatan-ivanov

* pr/44704:
  Add GarbageCollectorInfo to MemoryInfo

Closes gh-44704
This commit is contained in:
Moritz Halbritter 2025-03-17 09:09:57 +01:00
commit 77159205ed
2 changed files with 52 additions and 0 deletions

View File

@ -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 class ProcessInfo {
private static final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
private static final List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory
.getGarbageCollectorMXBeans();
private final MemoryUsageInfo heap;
private final MemoryUsageInfo nonHeap;
private final List<GarbageCollectorInfo> 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 class ProcessInfo {
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<GarbageCollectorInfo> getGarbageCollectors() {
return this.garbageCollectors;
}
public static class MemoryUsageInfo {
private final MemoryUsage memoryUsage;
@ -221,6 +243,27 @@ public class ProcessInfo {
}
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;
}
}
}
}

View File

@ -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 @@ class ProcessInfoTests {
assertThat(nonHeapUsageInfo.getUsed()).isPositive().isLessThanOrEqualTo(nonHeapUsageInfo.getCommitted());
assertThat(nonHeapUsageInfo.getCommitted()).isPositive();
assertThat(nonHeapUsageInfo.getMax()).isEqualTo(-1);
List<MemoryInfo.GarbageCollectorInfo> garbageCollectors = processInfo.getMemory().getGarbageCollectors();
assertThat(garbageCollectors).isNotEmpty();
assertThat(garbageCollectors).allSatisfy((garbageCollector) -> {
assertThat(garbageCollector.getName()).isNotEmpty();
assertThat(garbageCollector.getCollectionCount()).isNotNegative();
});
}
@Test