Is your Java application using more memory than the -xmx setting?

Paul Dally
2 min readJan 20, 2022

Java application developers often think about heap memory as the only class of memory that applies to applications. Unfortunately for those who might think that way, that is not correct. Furthermore, not appreciating this fact can impact the stability of your application.

You may have noticed that the rss (resident set size) of your Java application is larger than the value you specified for Xmx and wondered why that was. For any reasonably modern version of Java (8+), you should be aware of Metaspace. Metaspace is “used to manage memory for class metadata. Class metadata are allocated when classes are loaded.” Metaspace is by default unlimited (Java will allow it to grow without restriction). This can impact the stability of your application, because even if heap has been restricted to a particular value with Xmx, growth of Metaspace consumption can — for example — push a container’s memory consumption past the configured limit, at which point Kubernetes would kill the container due to OOM.

You might think that classes are only loaded at application startup, and would therefore be relatively static, but this is also often not the case. There are many libraries and coding patterns that dynamically create new classes as an application runs (think JDBC, some XML/JSON/YAML parsing classes, many things that use reflection, applications that load plugins, etc.). You generally don’t have to have a complete understanding (or even an incomplete understanding) of exactly how/where/why this is happening in your application, just accept that it likely is being done by some of your build dependencies.

As a result, if you have a Java process that has 8G available to it, you should not probably not specify -Xmx8G or (for Java applications in containers) -XX:MaxRAMPercentage=100. A good rule of thumb is to configure your heap such that it can only consume up to 75% of the available memory (but what is optimal or even viable can vary on a case-by-case basis).

You may also want to cap the amount of memory that Java is allowed to use for Metaspace instead of accepting the default unlimited value. This can be done with the -XX:MaxMetaspaceSize argument, for example:

-XX:MaxMetaspaceSize=200m

--

--

Paul Dally

AVP, IT Foundation Platforms Architecture at Sun Life Financial. Views & opinions expressed are my own, not necessarily those of Sun Life