About G1 Garbage Collector, Permanent Generation and Metaspace

We received some questions around the G1 garbage collector and the use of Permanent Generation with it. There seems to be some confusion that the Hotspot JVM does not use permanent generation when G1 is used as the garbage collector. Here’s some clarification:

JDK 7: PermGen

Permanent Generation still exists in JDK 7 and its updates, and is used by all the garbage collectors. In JDK7, the effort to remove the permanent generation was started and some parts of the data residing in the permanent generation were moved to either the Java Heap or to the native heap. Permanent generation was not completely removed and it still exists in JDK 7 and its updates. Here's the list of things that were moved out of the permanent generation in JDK7:

  • Symbols were moved to the native heap

  • Interned strings were moved to the Java Heap

  • Class statics were moved to the Java Heap

JDK7: G1 and PermGen

With G1 collector, PermGen is collected only at a Full GC which is a stop-the-world (STW) GC. If G1 is running optimally then it does not do Full GCs. G1 invokes the Full GCs only when the PermGen is full or when the application does allocations faster than G1 can concurrently collect garbage.

With CMS garbage collector, we can use option -XX:+CMSClassUnloadingEnabled to collect PermGen space in the CMS concurrent cycle. There is no equivalent option for G1. G1 only collects PermGen during the Full stop-the-world GCs.

We can use options PermSize and MaxPermSize to tune the PermGen space size according to the application needs.

JDK8: PermGen

Permanent generation has been completely removed in JDK 8. This work has been done under the bug https://bugs.openjdk.java.net/browse/JDK-6964458. Options PermSize and MaxPermSize have also been removed in JDK 8.

Email to openjdk alias regarding the PermGen elimination project: http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-September/006679.html

JDK8: Metaspace

In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace. There are some new flags added for Metaspace in JDK 8:

  • -XX:MetaspaceSize=<NNN> where <NNN> is the initial amount of space(the initial high-water-mark) allocated for class metadata (in bytes) that may induce a garbage collection to unload classes. The amount is approximate. After the high-water-mark is first reached, the next high-water-mark is managed by the garbage collector
  • -XX:MaxMetaspaceSize=<NNN> where <NNN> is the maximum amount of space to be allocated for class metadata (in bytes). This flag can be used to limit the amount of space allocated for class metadata. This value is approximate. By default there is no limit set.
  • -XX:MinMetaspaceFreeRatio=<NNN> where <NNN> is the minimum percentage of class metadata capacity free after a GC to avoid an increase in the amount of space (high-water-mark) allocated for class metadata that will induce a garbage collection.
  • -XX:MaxMetaspaceFreeRatio=<NNN> where <NNN> is the maximum percentage of class metadata capacity free after a GC to avoid a reduction in the amount of space (high-water-mark) allocated for class metadata that will induce a garbage collection.

By default class metadata allocation is only limited by the amount of available native memory. We can use the new option MaxMetaspaceSize to limit the amount of native memory used for the class metadata. It is analogous to MaxPermSize. A garbage collection is induced to collect the dead classloaders and classes when the class metadata usage reaches MetaspaceSize (12Mbytes on the 32bit client VM and 16Mbytes on the 32bit server VM with larger sizes on the 64bit VMs). Set MetaspaceSize to a higher value to delay the induced garbage collections. After an induced garbage collection, the class metadata usage needed to induce the next garbage collection may be increased.



is the PermGen collection in CMS really concurrent when the -XX:+CMSClassUnloadingEnabled option is present? I thought it was piggybacking on the remark phase which is Stop-The-World.

Posted by guest on March 25, 2014 at 07:02 PM IST #

Having the G1 Collector not performing the equivalent of CMS's perm gen sweeping and CMS class unloading is bad for many RMI servers and App servers.

Many people in the comms space want to use G1 in place of CMS as CMS causes stop-the-world collections due to heap fragmentation, whereas G1 is a compacting collector (so theoretically should not have the same frequency of stop the world collections).

RMI servers often take connections from RMI clients, and the Java RMI runtime (server side) allocates classloaders per connection. One of the major benefits of concurrent+low pause collectors is a major reduction in long pause (several second) GCs. Yet thats not the case for RMI servers ... which are very common.

App servers often have Application Deploy + Undeploy cycles whilst the JVM process is live. These cause classes and class loaders to be eligible for garbage collection.

Its great that there is sufficient transparency here that this information is being disclosed, but this policy for treatment of the permanent generation appears as oversight in the G1 collector and may hinder its adoption.

Posted by guest on April 01, 2014 at 07:09 AM IST #

With CMS when -XX:+CMSClassUnloadingEnabled is used, the classes are unloaded in the CMS cycle though not concurrently. They are unloaded in the remark phase of the CMS cycle which is a stop-the-world phase.

Posted by Poonam on April 02, 2014 at 04:10 PM IST #

What would be the recommended setting for MaxPermSize for use with G1 GC, would it be still similar to what we used with ParallelGC or should this setting be different? How to determine what it should be set to?

Posted by Pawel on April 03, 2014 at 01:19 AM IST #


You should not see much difference in the PermGen space requirements when you migrate from ParallelGC to G1 collector. To begin with I would recommend keeping the same setting for MaxPermSize and analyze the G1 GC logs. If you see Full GCs happening due to PermGen getting full then increase the value set for MaxPermSize.

Posted by Poonam on April 03, 2014 at 05:36 PM IST #

Good article Poonam. Two questions:

1. What is it that still resides in Permanent Generation in JDK 7? Is it the class metadata?
2. Is this applicable to all the various GCs in JDK 7 or only for G1 gc ?


Posted by Kannan on April 04, 2014 at 02:18 PM IST #


Yes, the classes metadata resides in the PermGen in JDK7 and this is true for all the collectors.


Posted by guest on April 05, 2014 at 06:31 AM IST #

I recently tried switching to G1GC and ran into a situation where tomcat appeared to crash due to a PermGen error on a webapp redeploy. The G1GC logs indicate several Full GCs which is consistent with how it has been described, but there is no indication of the fact that I was running out of PermGen:
2014-04-15T16:35:32.015+0000: 364584.229: Total time for which application threads were stopped: 0.1979430 seconds
2014-04-15T16:35:32.865+0000: 364585.079: Application time: 0.8498930 seconds
2014-04-15T16:35:32.865+0000: 364585.079: [Full GC 546M->282M(1280M), 2.3108810 secs]
[Eden: 43.0M(56.0M)->0.0B(94.0M) Survivors: 8192.0K->0.0B Heap: 546.5M(1280.0M)->282.7M(1280.0M)]
[Times: user=2.38 sys=0.00, real=2.31 secs]
2014-04-15T16:35:35.176+0000: 364587.390: Total time for which application threads were stopped: 2.3114740 seconds
2014-04-15T16:35:35.177+0000: 364587.390: Application time: 0.0001960 seconds
2014-04-15T16:35:35.177+0000: 364587.391: [Full GC 282M->282M(1280M), 1.8853960 secs]
[Eden: 0.0B(94.0M)->0.0B(94.0M) Survivors: 0.0B->0.0B Heap: 282.7M(1280.0M)->282.6M(1280.0M)]
[Times: user=1.92 sys=0.00, real=1.89 secs]
2014-04-15T16:35:37.062+0000: 364589.276: Total time for which application threads were stopped: 1.8858660 seconds
2014-04-15T16:35:37.074+0000: 364589.288: Application time: 0.0117270 seconds
2014-04-15T16:35:37.075+0000: 364589.288: [Full GC 282M->277M(1280M), 2.0369900 secs]
[Eden: 1024.0K(94.0M)->0.0B(94.0M) Survivors: 0.0B->0.0B Heap: 282.9M(1280.0M)->277.4M(1280.0M)]
[Times: user=2.07 sys=0.00, real=2.03 secs]

Posted by guest on April 15, 2014 at 11:19 PM IST #

Yes, there is a bug in G1 that it does not print the PermGen size change details with Full GC logs in JDK7. There is a bug JDK-8037275 filed for this
and we will be fixing it soon.


Posted by Poonam on April 16, 2014 at 06:28 AM IST #

The fix for JDK-8037275 has been integrated into jdk7u-dev and will be available in 7u80.


Posted by Poonam on May 06, 2014 at 06:35 AM IST #

Post a Comment:
  • HTML Syntax: NOT allowed



« March 2015