Oracle’s latest edition for Java – Java 8 was released in March 2014. As usual, tons of new features have been added. There is one major change in the Memory management area that I want to discuss today.
“So long PermGen, Hello Metaspace !!”
Oracle has completely gotten rid of ‘PermGen’ and replaced it with Metaspace.
What is PermGen ?
Short form for Permanent Generation, PermGen is the memory area in Heap that is used by the JVM to store class and method objects. If your application loads lots of classes, PermGen utilization will be high. PermGen also holds ‘interned’ Strings
The size of the PermGen space is configured by the Java command line option -XX:MaxPermSize
Typically 256 MB should be more than enough of PermGen space for most of the applications
However, It is not unusal to see the error “java.lang.OutOfMemoryError: PermGen space“ if you are loading unusual number of classes.
Gone are the days of OutOfMemory Errors due to PermGen space. With Java 8, there is NO PermGen. That’s right. So no more OutOfMemory Errors due to PermGen
The key difference between PermGen and Metaspace is this: while PermGen is part of Java Heap (Maximum size configured by -Xmx option), Metaspace is NOT part of Heap. Rather Metaspace is part of Native Memory (process memory) which is only limited by the Host Operating System.
So, what is the significance of this change?
While you will NOT run out of PermGen space anymore (since there is NO PermGen), you may consume excessive Native memory making the total process size large. The issue is, if your application loads lots of classes (and/or interned strings), you may actually bring down the Entire Server (not just your application). Why ? Because the native memory is only limited by the Operating System. This means you can literally take up all the memory on the Server. Not good.
It is critical that you add the new option -XX:MaxMetaspaceSize which sets the Maximum Metaspace size for your application.
Note that it is no longer sufficient to just monitor the Heap Size. You must also monitor the Metaspace which you can do by just keeping an eye on the ‘process size’ using your Operating System utilities (Example: ‘top’ in Unix/Linux, ‘Task Manager’ in Windows).
You can use the jmap command to print out Memory statistics of your current pre Java 8 application.
jmap -permstat <PID>
There you have it. With Java 8, PermGen is gone and Metaspace is in. Metaspace is part of Native Memory and NOT part of Java Heap. While this change may not be significant during development stage of the application, it is critical to consider this when going to production as you might not only bring down your application but bring down the entire server if your application eats up excessive Metaspace.
Make sure the Application Administrators and QA are made aware of this significant change and ensure adequate monitoring during QA phase (load testing) and in production.
PermGen is not part of the HEAP and is not controlled by Garbage collection
The maximum memory for Metaspace is controlled by -XX:MaxMetaspaceSize
Hi Michael, thanks for the corrections.
Good point on the -XX:MaxMetaspaceSize. I’ve updated the blog post.
On Permgen being part of Java Heap, there are contradicting documentation even in Java official website. In my experience, I’ve also seen changing permgen resulting in changes in Heap utilization. In any case, we don’t have to worry about Permgen going forward. 🙂
You might want to update the figure too 🙂
Hi Karun, Micheak is right. PermGen is NOT part Heap space.
Take a look on Oracle references in this S.O. Answer:
More, if you try to use JConsole you can see two different Memory Area.
– Eden space,
– Old gen,
– Survivor space.
Non Heap Memory:
– Code Cache
– Permanent Generation.
Hi! I’m having problems in a production enviroment, in relation of metaSpace memory.
Without MaxMetaSpaceSize: the memory increases, until the server goes down (as you tell in this note)
Setting MaxMetaSpaceSize value: the memory increases until max value. Then GC runs but doesn’t affect metaSpace usage. Finally CPU goes to 100% and the system collapse.
I’m going to set a new value of MaxMetaSpace, but probably will happen the same a bit later.
Thanks in advance!
Does sound like a memory leak from native libraries. Are you able to take a heap dump and analyze the heap ? While metaspace is not inside heap, heap dump might give us some clues. Check this blog post for instructions on how to use Eclipse Memory Analyzer to analyze heap dumps.
What is the OS and JVM version ?
We are facing such issues in production environment . Above solution works for docker container as well .
Thanks Karun for this article.
There is an mistake on the picture. Java heap isn’t part of Metaspace, there are separate parts of native memory
“PermGen also holds ‘interned’ Strings”. This was correct before Java 7. Interned Strings are in Heap since Java 7. Most importantly, it will be garbage collected.
I think There is no much Difference ,even if size increases ,entire Collapse, if so Can elaborate in which case feasible.