JVM:经典垃圾回收器简要总结

经典垃圾回收器

Serial收集器

单线程工作的收集器。低延迟。它的单线程意义不仅仅是它只会一个处理器或一条收集线程去完成垃圾收集工作,更强调在它进行垃圾收集时,必须暂停其他工作线程,直到它收集结束。

相较于其他收集器而言,其简单而高效,内存消耗(垃圾回收时存储的额外信息)小,对于单处理器来说,没有线程交互的开销,可以获得最高的单线程收集效率。Serial收集器对于运行在客户端模式下的虚拟机来说是一个很好的选择。


ParNew收集器

Serial收集器的多线程版本。低延迟,基于标记-复制。JDK9开始,只与CMS搭配使用。


Parallel Scavenge收集器

新生代收集器,基于标记-复制,并行,高吞吐量。


Serial Old收集器

是Serial收集器的老年代版本,单线程,标记-整理。主要客户端模式下的HotSpot虚拟机使用。在服务器模式下,可能有两种用途:1.在JDK5及之前与Parallel Scavenge搭配使用(Parallel Scavenge中有PS MarkSweep收集器进行老年代收集, 这个收集器与Serial Old几乎一样);(2)作为CMS收集器发生失败时的后备预案,在并发Concurrent Mode Failure时使用。


Parallel Old收集器

是Parallel Scavenge的老年代版本,支持多线程并发收集,基于标记-整理算法。


CMS(Conrrent Mark Sweep)收集器

其过程分为四个步骤:(1)初始标记(2)并发标记(3)重新标记(4)并发清除
优点:并发收集,低停顿
缺点:CMS收集器多处理器资源非常敏感; 由于CMS无法处理“浮动垃圾”,有可能出现“Concurrent Mode Failure”失败进而导致另一次完全“Stop The World”的Full GC的产生;基于“标记-清除”,收集结束会有大量空间碎片产生。


Garbage First收集器(G1收集器)

G1开创了基于Region的堆内存布局,其不再坚持固定大小以及固定数量的分代区域划分,而是把连续的java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间,Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。
Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量的一般半的对象即可判定为大对象。每个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待。

停顿时间模型:G1将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个java堆中进行全区域的垃圾收集。更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定的收集停顿时间,优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。

G1至少有以下关键的细节问题需要妥善解决:

  • Region里面存在的跨Region引用对象如何解决?–>每个Region都维护自己的记忆集,这些记忆集会记录别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围之内。G1的记忆集存储结构上本质上是一种哈希表,Key是别的Region的起始地址,Value是一个集合,里面存储的元素是卡表的索引号。

  • 在并发标记阶段如何保证收集线程与用户线程互不干扰地运行?–>首先解决的是用户线程改变对象引用关系时:原始快照。其次,垃圾收集对用户线程的影响还体现在回收过程中新创建的对象的内存分配上–>G1为每个Region设计了两个名为TAMS(Top at Mark Start)的指针,把Region中的一部分空间划分出来用于并发回收过程中的新对象分配,并发回收时新分配的对象地址都必须要在这两个指针位置以上。

  • 如何建立起可靠的停顿预测模型?–>G1的停顿预测模型基于衰减均值为理论基础来实现的。G1收集器会记录每个Region的回收耗时、标准偏差、置信度等统计信息。这里强调的 “衰减平均值”是指它会比普通的平均值更容易受到新数据的影响,平均值代表整体平均状态,但衰减平均值更准确地代表“最近的”平均状态。换句话说,Region的统计状态越新越能决定其回收的价值,然后通过这些信息预测现在开始回收的话,由哪些Region组成回收集才可以在不超过期望停顿时间的约束下获得最高的收益。

G1收集器的运作过程大致可划分为以下四个步骤:初始标记;并发标记;最终标记;筛选回收。

注意:虽然可以通过设置不同的期望停顿时间,但是这个时间也是在合理的范围之内(回收过程几十到一百,甚至接近两百毫秒都很正常)。如果设置很小,如20ms,很可能出现的结果就是,导致每次选出来的回收集只占堆内存中很小的一部分,收集器收集的速度逐渐跟不上分配器分配的速度。很可能一开始收集器还能从空闲的堆内存中获得一些喘息的时间,但应用运行时间一长就不行了,最终占满堆引发Full GC反而降低性能。

从G1开始,最先进的垃圾收集器的设计导向变味了追求能够应付内存的内存分配速率,而不追求一次把整个Java堆全部清理干净。

G1和CMS比较

低延迟垃圾收集器的追求愈加强烈


Shenandoah收集器

与G1最明显的3点区别:(1)支持并发的整理算法(2)目前默认不支持分代收集(3)摒弃了G1中耗费大量内存和计算资源去维护的记忆集。

工作过程大致分为九个阶段:初始标记;!并发标记;最终标记;并发清理;!并发回收;初始引用更新;!并发引用更新;最终引用更新;并发清理。“!”标记的是最重要的并发阶段


ZGC收集器

ZGC的运作过程大致分为以下四个大阶段:并发标记;并发预备重分配;并发重分配;并发重映射。


Epsolon收集器

为了隔离垃圾收集器与Java虚拟机解释、编译、监控子系统的关系,RedHat提出了垃圾收集器的同意接口,Epsilon是这个接口的有效性验证和参考实现。


如何选择合适自己应用的垃圾收集器?

  • 应用程序的主要关注点是什么
  • 运行应用的基础设施如何?
  • 使用JDK的发行商是什么?

参考:周志明 《深入理解Java虚拟机》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值