其他分享
首页 > 其他分享> > openJDK中各种垃圾回收器浅谈

openJDK中各种垃圾回收器浅谈

作者:互联网

本文的重点是把openJDK中多种主流垃圾回收器拉到一起,并对他们的特征、关注点、优劣势做对比分析,以期能在生产时间中根据业务场景选择合适的垃圾回收器。由于本文并非介绍各种垃圾回收器的内部实现细节,所以对垃圾回收器的工作过程只做整体描述。

openJDK中主流的垃圾回收器


截止到JDK12,openJDK支持的主流垃圾回收期如上图所示。其他比较小众的垃圾回收期虽然也很重要(如Epsilon),但由于用得比较少,所以没有画出来,在此略过。

Serial和Serial Old收集器

看名字就知道,这是单线程垃圾回收器。Serial负责新生代,Serial Old负责老年代。他们的工作过程很简单:垃圾达到一定内存上限,就把用户线程停下来(当然要在用户线程的安全区域内),用一个GC线程去回收垃圾。

ParNew和ParallelOld收集器

也是看名字就知道,这是多线程并发的垃圾回收器。他们和erial和Serial Old收集器的工作除了可以用多个线程做GC外,几乎没什么差别。

Parallel Scavenge收集器

这是新生代的收集器,相比其他新生代收集器,他的关注点是“最大吞吐量”(GC时间/程序运行时间总),也就是说,它不是很关注一次性把用户线程停顿多久,但是一段时间内花在GC上的时时间占总时长的百分比要控制在一个阈值内。

CMS收集器

全称是 ConCurrent Mark Sweep,看名字就只知道它采用标记-清理算法做GC。用于老年代对象GC,实际上,只有CMS的GC会只发生在老年代(Major GC),其他的老年代GC发生时,都是Full GC,整个堆一起回收的。
这是openJDK中第一款可以做到与用户线程并发的垃圾回收器,它关注的是用户线程停顿时间。用户线程停顿时间越短,反映在程序外部,程序的响应速度越高、延时越低。
它的过程大致如下:

G1 收集器

G1收集器简单地把堆分成新生代和老年代两个部分,而是先对分成一个个Region,再给这些Region分配不同的角色,比如哪些Region作为Eden区,哪些是survivor区。
G1最大的特定是可以承诺最大停顿时间(一定范围内,即使到一百多毫秒),当最大停顿时间要求较短时,G1就会把要收集的目标Region范围(collection set,简称CSet))减小,一次少收集写Region,停顿时间允许大些,它就一次多收集写Region。
因为G1也是分代的,那么它也分为两种模式来确定CSet:

Shenandoah收集器

Shenandoah收集器可以看成是G1的改进版,他们拥有相同的堆内存布局,在初始标记、并发标记等阶段的思路也基本一致,甚至还共享了许多代码。

ZGC收集器

ZGC是openJDK中最新的收集器,目前还没有正式商用化。ZGC除了三个短暂的和堆大小无关的停顿之外,整个GC过程几乎都是和用户线程并发的。ZGC使用染色指针来标记对象的存活状态、finalizable状态和指针引用的有效性,因此无需单独维护记忆集,在移动对象后也可以不急于更新指针。
ZGC不使用写屏障,而是采用读屏障,在读取一个对象时,采用读屏障去判断染色指针的remap位,如果为0,说明指针是脏指针,需要在转发表上找到新地址,并且把指针更新到新地址上,再回复remap位为1。如果remap为1,说明指正已经是新的了,直接读取对象即可。
ZGC的工作过程大致可以分为以下几步:

分类

是否可以和用户线程并行
关注点
思路转变
优缺点

参考

https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
https://wiki.openjdk.java.net/display/zgc
https://www.baeldung.com/jvm-zgc-garbage-collector
https://hllvm-group.iteye.com/group/topic/44381?page=2

标签:浅谈,标记,对象,openJDK,用户,并发,线程,垃圾,GC
来源: https://www.cnblogs.com/JMLiu/p/15834895.html