十种GC收集器及原理(3)—ParNew

ParNew是Java中的新生代并行垃圾收集器,使用复制算法,支持多线程。它能与CMS配合工作,但不能与Parallel Old搭配。三色标记法用于标记内存中的对象,确保无黑色对象引用白色对象,实现即时垃圾收集。ParNew可通过-XX:UseParNewGC选项启用,但在JVM 10及以上版本中已被移除。

ParNew是用于新生代的并行多线程垃圾收集器,采用“复制”算法,与"Parallel Scavenge"使用的算法相同。它与“ Parallel Scavenge”的不同之处在于,它具有使其可以在CMS中使用的增强功能。例如,“ ParNew”执行所需的同步,以便它可以在CMS的并发阶段运行。

                                                                   图3-1:并行多线程垃圾收集过程示意图

从上图可以看出,其在STW阶段运行的GC是多线程的,这与Serial收集器的单线程形成鲜明对比。

复制算法

复制算法也是包含“标记”阶段的,所以我们叫它“标记-复制”算法更为准确。“标记-复制”算法与“标记-整理”算法非常相似,因为它们也可以重新放置所有活动对象。重要的区别是,重定位的目标是一个不同的内存区域,作为被标记为活动对象的新家。标记-复制方法具有一些优点,因为复制可以在同一阶段与标记同时进行。缺点是需要另外一个存储区域,该存储区域应足够大以容纳活动对象。

                                                                         图3-2:“标记-复制”算法内存示意图

上文中提到的“标记”阶段,在JVM的实现中使用的“三色标记”法。

     三色标记法

       3种颜色即:白色(White),黑色(Black)和灰色(Grey):
       白色集:是一组可以回收其内存的对象集合。
       黑色集:是一组对象,可以从根访问,没有关联任何白色对象。黑色集中的对象不是收集对象。
       灰色集:包含可以从根访问的所有对象,但尚未扫描以查找对“白色”对象的引用。由于已知它们是从根部可以访问的,因此无法对其进行垃圾收集,并且在扫描后将其变为黑色集。
       在许多算法中,最初的黑色集从空开始,灰色集是直接从根引用的对象集,而白色集包括所有其他对象。内存中的每个对象始终都归属3种颜色集合之一。
       该算法执行过程,如下图所示:

       1.从灰色组中选择一个对象,然后将其移至黑色组。
       2.将其引用的每个白色对象移至灰色组。这样可以确保该对象及其引用的任何对象都不能被垃圾回收。
       3.重复最后两个步骤,直到灰色设置为空。
       4.当灰色设置为空时,扫描完成。黑色对象可以从根部到达,而白色对象则不能,并且可以进行垃圾收集。
       由于所有从根无法立即到达的对象都被添加到白色集合中,并且对象只能从白色移动到灰色,从灰色移动到黑色,因此该算法保留了一个重要的不变性-没有黑色对象引用白色对象。这样可以确保一旦灰色组为空,就可以释放白色对象。
这称为三色不变式。该算法的某些变体不能保留此不变性,而是使用所有重要属性均适用的修改形式。
        三色标记法具有一个重要的优势—可以“即时”执行,而无需在相当长的时间内停止系统。这是通过在分配对象时以及在变异过程中标记对象,并维护各种集合来实现的。通过监视集合的大小,系统可以定期(而不是根据需要)执行垃圾收集。而且,避免了在每个周期上都需要触摸整个工作集。

        "ParNew"可以与老年代的垃圾收集器"CMS"或"Serial Old"搭配来完成垃圾分代收集的工作。但是不能与"Parallel Old"搭配进行分代GC。如下图所示:

      为什么ParNew不能和Parallel Old一起工作?

“ParNew”用一种被收集的每一代为其提供特定界面的样式采集。例如,“ParNew”(和“Serial”)实现space_iterate()将对每个对象执行操作在新生代中。当使用“ CMS”或“ Serial Old”,GC可以使用space_iterate()来在新生代的对象上做一些工作。这使得收集器的混合搭配工作有效,但同时会增加一些额外负担。而且负担似乎是伴随收集器增多而线性增加的。或者,“Parallel Scavenge”(至少在“Parallel Old”出现之前)总是知道老年代是如何被收集的,可以直接调用“Serial Old”收集器中的代码。“Parallel Old”不是以“ParNew”样式编写的,因此当其进行工作时,“ParNew”并不知道。其实,“Parallel Scavenge”与“Parallel Old”搭配使用更为高效。

另外,可以在带有“ ParNew”标签的GC日志消息中标识用于新生代的ParNew收集器。在JVM 9和更早版本中,可以使用“ -XX:+ UseParNewGC”选项显式调用用于新生代的ParNew收集器。但是此选项已从JVM 10中删除。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值