Add flags: production JVM flag cheat sheet for Spring Boot on JDK 25/27
MaxRAMPercentage vs a hardcoded -Xmx, -XX:-UseContainerSupport, the ActiveProcessorCount lie, and which diagnostic flags are worth leaving on in prod, verified in real Docker containers on JDK 25 and JDK 27. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package com.ankurm.flagsdemo;
|
||||
|
||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Prints what the JVM actually resolved its container-relevant flags to, at
|
||||
* runtime, inside whatever cgroup it is running under. This is the live
|
||||
* version of what docs/output/*.txt captures from -XX:+PrintFlagsFinal; the
|
||||
* two should agree, and the post at ankurm.com cross-checks both.
|
||||
*
|
||||
* <p>Explained in the post:
|
||||
* https://ankurm.com/jvm-flags-for-spring-boot-in-containers-jdk-25-27/
|
||||
*
|
||||
* <p><strong>Delete this endpoint before shipping to a real service.</strong>
|
||||
* It leaks heap sizing and cgroup limits to anyone who can reach it.
|
||||
*/
|
||||
@RestController
|
||||
public class JvmDiagnosticsController {
|
||||
|
||||
private static final List<String> FLAGS_OF_INTEREST = List.of(
|
||||
"MaxRAMPercentage", "MinRAMPercentage", "InitialRAMPercentage",
|
||||
"MaxRAM", "MaxHeapSize", "InitialHeapSize", "MinHeapSize",
|
||||
"UseContainerSupport", "ActiveProcessorCount",
|
||||
"UseG1GC", "UseParallelGC", "UseZGC", "UseSerialGC",
|
||||
"UseCompactObjectHeaders", "ParallelGCThreads", "ConcGCThreads"
|
||||
);
|
||||
|
||||
@GetMapping("/internal/jvm-flags")
|
||||
public Map<String, Object> jvmFlags() {
|
||||
Map<String, Object> out = new LinkedHashMap<>();
|
||||
|
||||
OperatingSystemMXBean os =
|
||||
(OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
|
||||
Map<String, Object> hostView = new LinkedHashMap<>();
|
||||
hostView.put("availableProcessors", Runtime.getRuntime().availableProcessors());
|
||||
hostView.put("totalMemorySizeBytes", os.getTotalMemorySize());
|
||||
hostView.put("freeMemorySizeBytes", os.getFreeMemorySize());
|
||||
out.put("osMXBeanView", hostView);
|
||||
|
||||
MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
|
||||
MemoryUsage heap = mem.getHeapMemoryUsage();
|
||||
Map<String, Object> heapView = new LinkedHashMap<>();
|
||||
heapView.put("initBytes", heap.getInit());
|
||||
heapView.put("usedBytes", heap.getUsed());
|
||||
heapView.put("committedBytes", heap.getCommitted());
|
||||
heapView.put("maxBytes", heap.getMax());
|
||||
out.put("heap", heapView);
|
||||
|
||||
List<String> gcNames = ManagementFactory.getGarbageCollectorMXBeans()
|
||||
.stream().map(GarbageCollectorMXBean::getName).toList();
|
||||
out.put("garbageCollectors", gcNames);
|
||||
|
||||
HotSpotDiagnosticMXBean diag =
|
||||
ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
|
||||
Map<String, String> flagView = new LinkedHashMap<>();
|
||||
for (String name : FLAGS_OF_INTEREST) {
|
||||
try {
|
||||
flagView.put(name, diag.getVMOption(name).getValue());
|
||||
} catch (IllegalArgumentException notThisJvm) {
|
||||
flagView.put(name, "N/A on this build");
|
||||
}
|
||||
}
|
||||
out.put("resolvedFlags", flagView);
|
||||
|
||||
out.put("jvmInputArguments",
|
||||
ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
out.put("javaVersion", System.getProperty("java.version"));
|
||||
out.put("javaVmName", System.getProperty("java.vm.name"));
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user