G1垃圾收集器,永久带和元数据区

时间:2022-06-24 14:55:04

原文:https://blogs.oracle.com/poonam/entry/about_g1_garbage_collector_permanent?utm_source=tuicool

G1垃圾收集器,永久带和元数据区

我们收到了一些围绕G1垃圾收集器和使用永久带的一些问题。当G1作为垃圾收集器的时候,hotspot JVM并没有使用永久带,这看上起可能有点迷惑。下面是一些澄清:

JDK7:永久带

JDK7和它的更新中仍然存在永久带,所有的垃圾收集器都在使用。在JDK7里面,开始进行去掉永久带的努力,永久带中的一些数据已经被转移到java堆或者是native堆中了。但是,永久带并没有完全被移除,在JDK7和更新版本中仍然存在。下面列出了JDK7中从永久带移除的东西:

符号引用被移到了native堆
池化string对象被移到了java堆
Class对象、静态变量被移到了java堆

JDK7:G1和永久带

在G1垃圾收集器中,只有在进行full GC的时候,永久带才会被回收,这一过程是stop-the-world的。当不做Full GC的时候,G1运行是最优化的。只有当永久带满了或者应用分配内存的速度超过了G1回收垃圾的速度的时候,G1才会触发Full GC。

在CMS垃圾收集器中,我们可以使用-XX:+CMSClassUnloadingEnabled在CMS concurrent cycle中回收集永久带。在G1里面没有对应的设置。G1只有在stop-the-world的Full GC的时候,才会回收永久带。

我们可以根据应用的需要,设置PermSize和MaxPermSize参数来调优永久带的大小。

JDK8:永久带

JDK8中已经完全移除了永久带。这项工作是在这个bug:https://bugs.openjdk.java.net/browse/JDK-6964458推动下完成的。JDK8中,PermSize和MaxPermSize参数也一并移除了。

移除永久带项目的邮件:http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-September/006679.html

JDK8:元数据区

在JDK8中,类的元数据存放在native堆中,这个空间被叫做:元数据区。JDK8中给元数据区添加了一些新的参数。

-XX:MetaspaceSize=<NNN> <NNN>是分配给类元数据区(以字节计)的初始大小(初始高水位),超过会导致垃圾收集器卸载类。这个数量是一个估计值。当第一次到达高水位的时候,下一个高水位是由垃圾收集器来管理的。

-XX:MaxMetaspaceSize=<NNN> <NNN>是分配给类元数据区的最大值(以字节计)。这个参数可以用来限制分配给类元数据区的大小。这个值也是个估计值。默认无上限。

-XX:MinMetaspaceFreeRatio=<NNN>,<NNN>是一次GC以后,为了避免增加元数据区(高水位)的大小,空闲的类元数据区的容量的最小比例,不够就会导致垃圾回收。
-XX:MaxMetaspaceFreeRatio=<NNN>,<NNN>是一次GC以后,为了避免减少元数据区(高水位)的大小,空闲的类元数据区的容量的最大比例,超过就会导致垃圾回收。

默认情况下,类元数据的分配仅受限于可用的本地内存。我们可以使用新的MaxMetaspaceSize参数限定类元数据可用的本地内存的数量。它类似于MaxPermSize。当类元数据区使用量到达MetaspaceSize(32位机客户端模式12M,32位服务器模式16M,64位机会更大)的时候,会触发垃圾回收,然后回收掉无用的类加载器和class对象。MetaspaceSize的值设置的过大会延长垃圾回收时间。垃圾回收过后,引起下一次垃圾回收的类元数据空间的大小可能会变大。


原文:

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.