Java Memory: PermGen vs MetaSpace

Diagram showing JVM memory management before and after Java 8. PermGen is replaced with Metaspace.

The Java Virtual Machine (JVM) provides two major services for any Java application: memory management, and running the compiled byte codes. Much of the memory management is done by the garbage collector, and the compiled byte codes are run by the HotSpot compiler.

Garbage Collection Revision

The garbage collector plays a crucial role in managing heap memory. It tracks every object in the heap, and removes any unreferenced objects. The garbage collector also removes temporary objects and unused class metadata.

Java uses generational garbage collection. The more garbage collection events an object survives, the further it gets promoted into older generations. It starts in the young generation (which is divided into Eden and Survivor spaces), and eventually ends up in the tenured (old) generation if it survives long enough. See the previous post on garbage collection

JVM Memory

The JVM memory is divided into two main groups: heap and non-heap.

All Java programmers probably know about the heap. The heap stores the objects that are created while a Java application runs. After a new instance of an object is created, it lives in the heap until it is no longer referenced. Then the garbage collector can free the memory allocated to that object. This implies that the heap size can change dynamically as the application runs.

The JVM initialises the heap at start-up. We can configure some heap size settings using the -XX:MaxHeapSize (or -Xmx), -XX:InitalHeapSize (or -Xms), -XX:NewSize (or -Xmn) and -XX:MaxNewSize JVM options.

Non-heap memory makes up the rest of JVM memory. Non-heap memory is divided into several different areas, each storing different data. This includes JVM code and internal structures, the constant pool, interned strings, field and method metadata, and the code for methods and constructors.

PermGen

An important part of the non-heap memory is allocated to PermGen (the permanent generation). This is a pool containing reflective data of the virtual machine itself, such as class and method objects. PermGen contains metadata required by the JVM to describe the classes and methods used in the application. It is populated at runtime with these application classes, as well as Java SE library classes and interned strings.

Even though PermGen is not part of the main heap, it is included in a full garbage collection. Classes may get unloaded (garbage collected) if they are no longer needed and space is required for other classes.

The maximum size of PermGen is fixed using the -XX:MaxPermSize=size option. There is no way to make PermGen auto-increase past this allocated size. Because of this fixed size, PermGen is difficult to tune.

Metaspace

From Java 8 PermGen was replaced by a new memory area called Metaspace. It has the same role as PermGen which is to store class metadata. Metaspace is not part of the JVM heap, but is allocated in native operating system memory. It can auto-increase as needed to load additional class metadata.

When PermGen was originally introduced, there was no dynamic class unloading. Once a class was loaded, it was stuck in memory permanently until the JVM was shut down (hence the “PermGen” name). These days classes can be loaded and unloaded during the lifespan of the JVM. “Metaspace” is better suited as a name for the area where the metadata is kept.

Metaspace can auto-increase its size up to what the operating system can provide. We can set a fixed maximum size for Metaspace using the -XX:MaxMetaspaceSize flag. The default maximum size is unlimited, which means that the operating system memory is the only limit.

Garbage collection of the dead classes and class loaders is triggered once the class metadata usage reaches the -XX:MetaspaceSize limit.

With the removal of PermGen, we will never get another OutOfMemoryError: PermGen error. Obviously the -XX:PermSize and -XX:MaxPermSize JVM options are now ignored.

ClassLoader Leaks

Both PermGen and Metaspace can suffer from ClassLoader leaks. The removal of PermGen doesn’t mean that our class loader leak issues are gone. We still have to monitor memory usage and plan accordingly.

The default JVM settings for Metaspace allow it to automatically increase its size as needed. It will obviously then take longer before the effects of any ClassLoader leaks are seen. This just pushes the problem further away without necessarily solving it. A leak could end up consuming our entire native memory. The effect of running out of OS memory will probably be more severe than running out of JVM PermGen memory.

Since the class metadata is allocated from native operating system memory, the maximum available space is the total available system memory. Thus, we will no longer get OutOfMemoryErrors, but could end up spilling into the operating system swap space.

Further Reading

For more technical details on the removal of the permanent generation, see JEPS 122.

For new developments on Metaspace, see JEP 387: Elastic Metaspace.

There’s a good PermGen vs Metaspace article on DZone. As well as a nice short one on Baeldung.

There are two nicely illustrated technical articles on the Java-Latte blogspot, one on garbage collection, the other on Metaspace. They’re about 10 years old, but still relevant.

Was this interesting? Please share your comments, and as always, stay safe and keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.