If you are not a newcomer to the Java landscape, you might be familiar with another concept in Java memory management called PermGen. Starting from Java 8, the memory model in Java was significantly changed. A new memory area called Metaspace was introduced and Permgen was removed. This change was made due to variety of reasons, including but not limited to:
- The required size of permgen was hard to predict. It resulted in either under-provisioning triggering java.lang.OutOfMemoryError: Permgen size errors or over-provisioning resulting in wasted resources.
- GC performance improvements, enabling concurrent class data de-allocation without GC pauses and specific iterators on metadata
- Support for further optimizations such as G1 concurrent class unloading.
So if you were familiar with PermGen then all you need to know as background is that – whatever was in PermGen before Java 8 (name and fields of the class, methods of a class with the bytecode of the methods, constant pool, JIT optimizations etc) – is now located in Metaspace.
As you can see, Metaspace size requirements depend both upon the number of classes loaded as well as the size of such class declarations. So it is easy to see the main cause for the java.lang.OutOfMemoryError: Metaspace is: either too many classes or too big classes being loaded to the Metaspace.