原文链接,译者:Greenster
简介
Oracle在JDK7 update 4之后开始完全支持G1垃圾收集器,G1是一个针对多处理器大容量内存的服务器端的垃圾收集器,其目标是在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求。G1在执行一些Java堆空间中的全区域操作(如:全局标记)时是和应用程序线程并发进行的,因此减少了Java堆空间的中断比例。(译者注:可简单理解为减少了Stop-the-World的时间比例)
技术说明
G1收集器通过下面一些方法实现了高性能和减少暂停时间的目的。
首先将Java堆空间划分为一些大小相等的区域(region),每个区域都是虚拟机中的一段连续内存空间。G1通过执行并发的全局标记来确定整个Java堆空间中存活的对象。标记阶段完成后,G1就知道哪些区域基本上是空闲的。在回收内存时优先回收这些区域,这样通常都会回收相当数量的内存。这就是为什么它叫做Garbage-First的原因。顾名思义G1关注某些区域的回收和整理,这些区域中的对象很有可能被完全回收。而且G1使用了一个暂停时间预测模型使得暂停时间控制在用户指定的暂停时间内,并根据用户指定的暂停时间来选择合适的区域回收内存。
G1确定了可回收的区域后就是筛选回收(evacuation)阶段了。在此阶段将对象从一个或多个区域复制到单一区域,同时整理和释放内存。该阶段是在多个处理器上多个线程并行进行的,因此减少了暂停时间并提高了吞吐量。G1在每一次的垃圾收集过程中都不断地减少碎片,并能够将暂停时间控制在一定范围内。这些已经是以前的垃圾收集器无法完成的了。比如:CMS收集器并不做内存整理。ParallelOld收集器只是对整个Java堆空间做整理,这样导致相当长的暂停时间。
关于G1很重要的一点是它并不是一个实时收集器。尽管在绝大多数情况下都能够满足暂停时间的要求,但并非没有例外。因为G1是基于之前数次垃圾收集的经验值来估计在用户指定的暂停时间内有多少区域可以收集。因此它对于在区域上执行收集的成本有一个合理的较为精确的模型,并使用该模型来确定对哪些区域执行收集。
对于更详细的关于使用和配置G1的信息请参考JAVA虚拟机参数。
推荐使用的场景
G1的首要目的是为那些需要大容量内存和较小GC延迟的应用程序提供解决方案。这通常是指那些堆大小设置在6GB以上,确定的、可以预测的暂停时间在0.5秒以内的应用程序。
如果应用程序符合以下一项或者多项特征,那么从CMS或者ParallelOld收集器切换到G1可能更合适。
- 活动对象占据了超过50%的Java堆空间。
- 对象分配率或者提升率波动明显。
- 不希望有长时间的垃圾收集暂停时间(超过0.5秒或1秒)。
G1的前景
G1的使命是替换掉CMS收集器。通过对比G1和CMS收集器,可以发现G1是更好的一种解决方案。首先G1是一个压缩收集器,G1通过充分的压缩完全避免了使用细粒度的空闲列表(free lists)来分配内存,而是使用相对粗粒度的区域(regions)来分配内存。这明显简化了收集器,也很大程度上减少了内存碎片化的问题。此外,相比较CMS,G1可以预测出垃圾收集的暂停时间,并允许用户指定期望的暂停时间。
如果你有兴趣改善G1,请通过OpenJDK和邮件列表hotspot-gc-use@openjdk.java.net给我们反馈。