Demo application to show JVM ergonomics behaviour depending on the Java 8 version
Prior to Java 8u191, Java configuration in Docker containers was a bit tricky because
JVM Ergonomics set some values
(like CPU cores or Heap memory limit) based on Docker daemon configuration. This behaviour forced to set JVM limits
explicitly (with -Xmx for example) or via command line options (like -XX:+UseCGroupMemoryLimitForHeap). Now, with Java
8u191 or Java 10, the JVM sets theses values based on Docker container’s configuration instead of Docker daemon.
We’ll compare these different behaviours running a demo application in Java 8u121 and Java 8u191. Unlike the former, the
latter is a container aware Java version.
The application visualizes the number of CPU cores and the memory limit in the logs:
public static void main(String[] args) {
long memory = Runtime.getRuntime().maxMemory();
int cpuCores = Runtime.getRuntime().availableProcessors();
LOGGER.info("Max Java Memory (MB): {}", memory / (1_024 * 1_024));
LOGGER.info("Max Java CPU Cores: {}", cpuCores);
}
We’ll see that the values are different depending on the Java version.
This demo only requires Docker installed in your computer.
Clone this repo:
git clone https://github.com/wearearima/docker-java-cpu-memory-limit.git
Move to the downloaded repo, cd docker-java-cpu-memory-limit
, and build same image with different Java versions:
docker build -t eu.arima/docker-java-cpu-memory-limit:java8u121 -f Dockerfile_java8u121 .
docker build -t eu.arima/docker-java-cpu-memory-limit:java8u191 -f Dockerfile_java8u191 .
We can check the new images invoking docker image ls
:
REPOSITORY TAG IMAGE ID CREATED SIZE
eu.arima/docker-java-cpu-memory-limit java8u121 7e26f907aed2 29 hours ago 92.2MB
eu.arima/docker-java-cpu-memory-limit java8u191 c4eabbac6bd6 29 hours ago 88.6MB
Before comparing how JVM ergonomics behaves in each version, let’s find out how much memory and how many cpu cores are
configured in Docker daemon. To do so execute:
docker info
This command returns all information about Docker daemon’s configuration. For this demo we only pay attention to CPUs
and Total memory
parameters. In my case these are the values:
CPUs: 2
Total Memory: 5.818GiB
Therefore, I’ve got configured 2 CPU cores and almost 6GB memory for all my containers.
For demonstration purposes, containers’ memory and cpu will be limited running theses commands:
docker run --memory=1GB --cpus=1 eu.arima/docker-java-cpu-memory-limit:java8u121
docker run --memory=1GB --cpus=1 eu.arima/docker-java-cpu-memory-limit:java8u191
Memory is limited to 1 GB with --memory=1GB
option and CPU to one core with --cpus=1
option.
The result is:
Feature | Java 8u121 | Java 8u191 |
---|---|---|
Max Java Memory (MB) | 1324 | 247 |
Max Java CPU Cores | 2 | 1 |
With Java 8u191 java ergonomics has calculated the memory and cpu limits based on the configuration of the container
(1GB and 1 cpu). However, the container with Java 8u121 has calculated these features based on the Docker daemon
configuration (5.818GiB and 2 cpus).
Useful links: