JVM settings inside a container
Size the heap against the container limit so the kernel stops killing your Java process.
Open this lesson in the learning hubKey points
- Since Java 10 the JVM reads cgroup limits, not the host specs.
UseContainerSupportis on by default. - Default max heap is only 25% of the container memory limit. On a 1 GB container that is about 256 MB.
- Prefer
-XX:MaxRAMPercentage=75over a hard-coded-Xmx. It follows the limit when you resize the container. - Heap is not the whole footprint. Metaspace, thread stacks, code cache and direct buffers live outside it, so leave headroom.
- Exit code 137 means the kernel OOM-killed the process. Raise
--memoryor lower the percentage. - CPU limits shrink
availableProcessors()and therefore your GC and ForkJoin pools. Under 2 CPUs the JVM falls back to SerialGC.
Example
# always set a limit, then size the heap against that limit
docker run -d --memory=1g --cpus=2 -p 8080:8080 \
-e JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75 -XX:+UseG1GC" \
myapp:1.0
# what does the JVM believe it has?
docker run --rm --memory=1g eclipse-temurin:21-jre \
java -XX:+PrintFlagsFinal -version | grep -E "MaxHeapSize|MaxRAMPercentage|ActiveProcessorCount"
# it died. why?
docker inspect --format '{{ .State.ExitCode }} {{ .State.OOMKilled }}' myapp
Set --memory, then set MaxRAMPercentage. Never let the JVM guess.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Docker course, and every lesson in it is listed on the Docker contents page.