No pun intended
The JDK 8u131 has backported a nice feature in JDK 9, which is the ability of the JVM to detect how much memory is available when running inside a Docker container.
I have talked multiple times about the problems running a JVM inside a container, how it will default in most cases to a max heap of 1/4 of the host memory, not the container.
For example in my machine
$ docker run -m 100MB openjdk:8u121 java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 444.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM
Wait, WAT? I set a container memory of 100MB and my JVM sets a max heap of 444M ? It is very likely that it is going to cause the Kernel to kill my JVM at some point.
Let’s try the JDK 8u131 with the experimental option -XX:+UseCGroupMemoryLimitForHeap
$ docker run -m 100MB openjdk:8u131 java \ -XX:+UnlockExperimentalVMOptions \ -XX:+UseCGroupMemoryLimitForHeap \ -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 44.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM
Ok this makes more sense, the JVM was able to detect the container has only 100MB and set the max heap to 44M.
Let’s try in a bigger container
$ docker run -m 1GB openjdk:8u131 java \ -XX:+UnlockExperimentalVMOptions \ -XX:+UseCGroupMemoryLimitForHeap \ -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 228.00M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM
Mmm, now the container has 1GB but JVM is only using 228M as max heap. Can we optimize this even more, given that nothing else other than the JVM is running in the container? Yes we can!
$ docker run -m 1GB openjdk:8u131 java \ -XX:+UnlockExperimentalVMOptions \ -XX:+UseCGroupMemoryLimitForHeap \ -XX:MaxRAMFraction=1 -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 910.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM
Using -XX:MaxRAMFraction
we are telling the JVM to use available memory/MaxRAMFraction as max heap. Using -XX:MaxRAMFraction=1
we are using almost all the available memory as max heap.
UPDATE: follow up for Java 10+ at Running a JVM in a Container Without Getting Killed II