user1236097
user1236097

Reputation: 303

java.lang.OutOfMemoryError: Compressed class space

We are running on java-8-oracle.

We moved to java8 six month ago.

In the past few days we have been getting an OOME from time to time and we haven't been able to identify or reproduce the problem.

When we execute a call to the server (tomcat) we get this error on the stacktrace:

java.lang.OutOfMemoryError: Compressed class space

Restarting the server solves the problem. The same call to other server works, and so does another call of another type to the same server.

When looking on the gc.log we see:

2015-05-27T16:05:42.991+0000: 98774.440: [Full GC (Last ditch collection) 98774.440: [CMS: 575745K->575330K(3495936K), 0.8687777 secs] 575745K->575330K(4107008K), [Metaspace: 97940K->97940K(1396736K)], 0.8696093 secs] [Times: user=0.95 sys=0.00, real=0.88 secs]
2015-05-27T16:05:55.486+0000: 98786.935: [Full GC (Metadata GC Threshold) 98786.935: [CMS: 573414K->578735K(3495936K), 0.9372859 secs] 925046K->578735K(4107008K), [Metaspace: 99428K->99428K(1396736K)], 0.9386626 secs] [Times: user=1.01 sys=0.00, real=0.94 secs]

jstat -gc returns:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
87296.0 87296.0  0.0   3151.4 523776.0 148284.4 3495936.0   574868.5  1395640.0 98066.3 1048576.0 11339.1  12165  636.851  223   116.957  

753.808

I don't see any memory problems either in the jstat log or in the gc log.

Trying to run jmap -clstats hangs:

Attaching to process ID 5110, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.25-b02
finding class loader instances ..

Upvotes: 17

Views: 32010

Answers (3)

Nirmal
Nirmal

Reputation: 109

You can fix this issue by using one of the two options below.

1. You can increase the limit of class space by using -XX:CompressedClassSpaceSize=n VM flag. Maximum limit is 4GB.

(OR)

2. You can completely disable Compressed class pointer feature by using -XX:-UseCompressedClassPointers VM flag.

Note: Please be aware that disabling this feature will increase heap space usage of your application.

From "Java Performance Optimization: Compressed OOPS" book

Each object has a pointer (_klass) to VM metadata class. This pointer is also compressed on 64-bit JVM. In JDK 8, permanent generation was removed and replaced by metaspace memory. This metaspace is dynamically growing memory and can reach native memory limit if the VM flags are not configured to control this metaspace memory. Prior Java 8, permanent memory is used and its size is fixed with VM flags. It can’t change its size at run time. When compared with heap memory space, this permanent memory space (non-heap) is very small and will usually be within 4GB limit to store class metadata and other metadata. So the virtual memory address range can be 0 to 4 GB if the zero-based virtual memory is assigned by operating system to this permanent memory. So compressing the memory addresses of klass objects using only 32-bits in this permanent memory location is not a problem.

But in Java 8, permanent memory is replaced with metaspace in order to support some performance improvements. This memory location can grow till it reaches the native memory limit if -XX: MaxMetaspaceSize VM is not set to control this growth. If it can grow till the native memory limit, then the klass objects might also be stored at any higher memory boundaries. This will be a problem to compress that memory location using 32-bit offset. So in order handle this problem and allocate a separate memory space for klass instances alone, Java introduced a new memory space called “compressed class space” in Java 8 version. The inclusion of compressed class space memory in Java 8 introduced “Java.lang.OutOfMemoryError: Compressed class space”. This OutOfMemoryError is triggered when the compressed class space memory reaches its maximum default capacity of 1 GB and there are no more room to store additional klass instances

In order to know more details about this OutOfMemoryError and about klass filed, you can read below books.

https://javaperformanceoptimization.com/

  1. Java Performance Optimization: Compressed OOPS
  2. Java Performance Optimization: How to avoid the 10 OutOfMemoryErrors

Upvotes: 2

Albert
Albert

Reputation: 159

We faced a similar issue. Unfortunately heapdumps won't help you since the classes are not in the heap but in native memory. Enable these in your JVM settings to troubleshoot the classes loaded:

-XX:+PrintGCDetails -XX:+TraceClassUnloading -XX:+TraceClassLoading

In our case the issue was JAXBContext.newInstance not being singleton.

Good luck, Albert

Upvotes: 15

the8472
the8472

Reputation: 43125

With compressed oops and compressed class pointers the available space for classes is constrained due to the necessary pointer mangling. 1GB in your case.

That's a lot of classes, so this might be an indicate that something in your application is creating a lot of classes and never releasing them. Application reload maybe?

If you are certain that your application just needs that much memory for classes you can try bumping the limit via -XX:CompressedClassSpaceSize=... or disabling compressed class pointers via -XX:-UseCompressedClassPointers.

Note that by default compressed class space + compressed heap (+ some overhead) cannot exceed 32GB. Although, AIUI, changing object alignment can bump that limit further.

Otherwise you should take a heapdump and analyze what's holding onto the loaded classes.

Upvotes: 7

Related Questions