≡ Menu

One important change in Memory Management in Java 8


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.

Java8 heap

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).

Bonus Tip:

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.

Good Luck




{ 10 comments… add one }
  • Michael Lightfoot November 20, 2017, 10:44 pm

    PermGen is not part of the HEAP and is not controlled by Garbage collection
    The maximum memory for Metaspace is controlled by -XX:MaxMetaspaceSize

    • Karun Subramanian November 25, 2017, 11:46 am

      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. 🙂

      • palacsint December 1, 2017, 3:09 pm

        You might want to update the figure too 🙂

      • SamuelJ June 4, 2018, 7:43 am

        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.
        Heap Memory:
        – Eden space,
        – Old gen,
        – Survivor space.

        Non Heap Memory:
        – Code Cache
        – Permanent Generation.

  • José May 9, 2018, 7:19 pm

    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.

    Any suggestion?
    Thanks in advance!

    • Karun Subramanian May 10, 2018, 4:16 am

      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 ?

  • Mahesh June 5, 2018, 12:01 pm

    We are facing such issues in production environment . Above solution works for docker container as well .
    Thanks Karun for this article.
    — Mahesh

  • Vasyl June 22, 2018, 10:11 am

    There is an mistake on the picture. Java heap isn’t part of Metaspace, there are separate parts of native memory

  • Jacob May 25, 2019, 5:17 am

    “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.

  • vinay December 28, 2019, 5:33 pm

    I think There is no much Difference ,even if size increases ,entire Collapse, if so Can elaborate in which case feasible.

Leave a Comment