A first experimental change has been added to OpenJDK 9 so the JVM can understand that it is running within a container and adjust memory limits accordingly. Despite the increase in popularity of containers in the last few years, many tools, including the JVM, still rely on the host's parameters to assess available resources, oftentimes running out of memory with baffling error messages. This change, that could be available to the public once Java 9 is released, tries to prevent many of those scenarios.
Container technologies such as Docker, Heroku or Kubernetes, among others, are a form of lightweight virtual machines based on the Linux operating system. Their reduced footprint means they can provide a very similar functionality to virtual machines faster and consuming fewer resources, but it also comes with disadvantages: while full-blown virtual machines simulate a whole stack of dedicated hardware, meaning existing software works mostly as expected, container technologies use the host's hardware and OS, meaning that software that relies on host information might run unaware of the extra constraints that containers impose. Fabio Kung, developer of the Linux containers service at Netflix (also known as Titus), wrote a good article explaining these effects in 2014; although some contents of the article might be outdated by now, it still serves as a good introduction to the topic.
The JVM is no stranger to this. If the maximum memory limit hasn’t been specified with -Xmx
, the JVM will set it as a fraction of the physical memory (typically a fourth, but it may vary); this may not take into account the limits imposed by the container. The proposed change aims at preventing this problem by checking whether the JVM is running within a Control Group or cgroup, a Linux technology most container technologies use to enforce limits on the use of hardware and other resources. If the JVM detects it is running within a cgroup, it will try to find the memory limit defined in it and consider such limit as the available physical memory, setting every other parameter as a function of this. This is still experimental, and therefore will only be applied if activated with the option -XX:+UseCGroupMemoryLimitForHeap
.
Incorporated to the Linux kernel in 2008 and redesigned in 2013, cgroups isolate resource usage and allow applications to control access to memory, CPU, IO, and networking, among others. Different applications can create their own hierarchies of control groups with different limits per group, meaning an application doesn’t know, a priori, the group it will run in. This is why the JVM can only make a guess regarding cgroups and the potential memory limit in place.