How to solve java.lang.OutOfMemoryError: Compressed class space error

This article describes how to fix the error “java.lang.OutOfMemoryError: Compressed class space error” which is an error that can occur on a 64-bit platform.

Anatomy of Class Space Memory

Starting with Java 1.8, loaded classes are confined to a native space called the “Compressed Class Metadata Space” or CCMS.

The default size for the Compressed Class Metadata Space is 1Gb of memory, unless you specify a different value on the JVM command line. When classes are being loaded by the classloader, the JVM tries to allocate the metadata to the CCMS. If the JVM cannot make room for the CCMS arena, the Compressed class space error is thrown. So in most cases, the simplest solution is to increase the CompressedClassSpaceSize value, for example to 2 GB:

-XX:CompressedClassSpaceSize=2g

The variables which we should consider are however two:

  • MaxMetaspaceSize is the maximum amount of memory that you can commit to the sum of Class metadata and Compressed Class spaces. If you don’t specify this option, the Metaspace will dynamically re-size depending of the application demand at runtime.
  • CompressedClassSpaceSize is the amount of virtual memory reserved just for the compressed class space.

As a rule, you should set the MaxMetaspaceSize to be larger than the CompressedClassSpaceSize as in the following example:

-XX:MaxMetaspaceSize=512m -XX:CompressedClassSpaceSize=256m 

We can check the values for both variables with ‘jcmd’ passing as argument the PID of the Java process and “VM.metaspace”:

 jcmd 13966 VM.metaspace

  . . 
MaxMetaspaceSize: 512.00 MB
InitialBootClassLoaderMetaspaceSize: 4.00 MB
UseCompressedClassPointers: true
CompressedClassSpaceSize: 256.00 MB

Warning

You cannot rely on the -XX:+HeapDumpOnOutOfMemoryError option to produce an Heap Dump for this kind of error as as HeapDumpOnOutOfMemoryError only works if you run out of Heap Memory.

As you can see from the above output, our setting for CompressedClassSpaceSize has been committed in the JVM.

Conversely, if you set MaxMetaspaceSize to a lower value than than CompressedClassSpaceSize, the JVM will self-adjust the CompressedClassSpaceSize based on the following formula:

CompressedClassSpaceSize = MaxMetaspaceSize – 2 * InitialBootClassLoaderMetaspaceSize

For example, we will be using the following JVM options:

-XX:MaxMetaspaceSize=256m -XX:CompressedClassSpaceSize=512m

Running again jcmd against the Java process reveals the actual value for CompressedClassSpaceSize:

MaxMetaspaceSize: 256.00 MB
InitialBootClassLoaderMetaspaceSize: 4.00 MB
UseCompressedClassPointers: true
CompressedClassSpaceSize: 248.00 MB

Finally, it is worth noting that you can disable both UseCompressedClassPointers and UseCompressedOops which allows the JVM to load as many classes as they fit into memory. That will bypass the limited imposed by CompressedClassSpaceSize virtual memory region.

You can check the default values for your JDK as follows:

$ java -XX:+PrintFlagsFinal -version | grep Compressed

     size_t CompressedClassSpaceSize               = 1073741824                                {product} {default}
     bool UseCompressedClassPointers               = true                                 {lp64_product} {ergonomic}
     bool UseCompressedOops                        = true                                 {lp64_product} {ergonomic}
java version "11.0.4" 2019-07-16 LTS
Found the article helpful? if so please follow us on Socials