JAVA 7 G1收集器调研

最近在看虚拟机垃圾收集,看到了JAVA 7 G1收集器的相关内容,特深入调研了下。

G1收集器全称Garbage-First Garbage Collector。是在Java 6 Update 14中引入,旨在取代CMS收集器的一种新型收集器。在Java 6中只是试验性的引入,因各种原因没有正式引入。Java 7开始,其被正式引入。

作为一个server-style回收器,其具有如下属性:

1. 并行和并发

众所周知,目前所有的GC(无论是serial,parallel及近年来广泛使用的CMS)均存在暂停时间问题,所谓的暂停时间是由于GC的“stop-the-world” 机制(这个机制简称STW,即,在执行垃圾收集算法时,Java应用程序的其他所有除了垃圾收集帮助器线程之外的线程都被挂起)。而G1 可以从最新的硬件中获得并行的能力。它能够使用所有可用的CPU(CPU多核,硬件多线程,等)来加速它的STW暂停时间。虽然其并行机制在CMS中已有了一定的实现(即周期性的进行并发标记[concurrent marking phase]),但G1采用了新的实现方式。

该机制与G1新的堆内存管理机制相关。与其他GC收集器不同,在G1中,对象的新生代和老一代上并没有在物理上分隔开,而是把一个连续的堆内存拆分成了几个相同大小的区域。新生对象和老对象都会被放在一系列可能不连续的区域中。之所以这样做,就是为了让G1可以更灵活地移动老对象所占用的资源给新的对象。G1中的内存收集会发生 “疏散暂停”,当内存从一系列区域开始回收时,这些区域所引用的对象会被疏散到另一些区域中,这样,会有一整块的内存来重新被申请(其思想跟垃圾收集算法中的复制算法很类似)。疏散会发生整个程序的暂停,但“疏散”这些内存可以被并行运行,这正是G1的并发阶段做的事情。

2. 分代处理

与其它的HotSpot 垃圾回收器一样,G1 也是分代的。即它在处理新分配的对象(年轻代)和已经生存了一段时间的对象(年老代)时会不同,它会更多地考虑一些新创建的对象实例,因为越新创建的就越有最大的可能性被回收,老对象只是偶尔访问一下。对于大多数的Java应用来说,这个机制可以极大地提高回收效率。

3. 紧凑内存(碎片整理

与CMS收集器不同,G1 会对堆进行内存整理。压缩可以消除潜在的内存碎片的问题,这样程序就可以更长时间的平滑运行。

4. 预见性

G1 比起 CMS 来有更多的预见性。这个主要还是用来消除内存碎片的问题。内存的碎片少了,STW的暂停时间也会被减少。

目前G1仍然还在试验阶段,使用下面两个参数可以打开G1机制:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

目前G1收集器还存在如下问题:

  1. G1不支持 JVM TI JMX等工具,由于相当数量的JVM管理及监控工具都是基于这两个服务的,因此基于G1很多工具无法正确使用。
  2. G1不支持增量永生代收集。因此,在应用卸载类时,无法进行收集。
  3. STW的暂停时间不太稳定,与CMS相比,时好时坏。