jdk各版本垃圾收集器介绍

七款经典垃圾收集器:

如果两个收集器之间存在连线,就说明它们可以搭配使用,图中收集器所处的区域,则表示它是属于新生代收集器抑或是老年代收集器

JDK各版本默认GC

版本默认 GC 变化备注
JDK 1.3Serial →经典串行收集器
JDK 1.4→ Parallel(可选)引入多线程 GC
JDK 1.5Parallel 成为默认(Server 模式)吞吐量优先
JDK 1.6 / 1.7 / 1.8Parallel 默认,G1 可选CMS 逐步被弃用
JDK 9G1 成为默认目标:平衡吞吐 + 低停顿
JDK 11仍默认 G1;ZGC 加入(可选)ZGC 初次正式出现
JDK 15Shenandoah 加入OpenJDK 全支持
JDK 17+默认仍 G1,可选 ZGC / ShenandoahLTS 稳定版
JDK 21新增 Generational ZGC延迟更低、效率更高

Serial收集器

最基础、历史最悠久的收集器,是一个单线程工作的收集器,工作于新生代,使用标记-复制算法:

对于单核处理器或处理器核心数较少的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。Serial收集器对于运行在客户端模式下的虚拟机来说是一个很好的选择

ParNew收集器

ParNew收集器实质上是Serial收集器的多线程并行版本,ParNew收集器除了支持多线程并行收集之外,其他与Serial收集器相比并没有太多创新之处,工作于新生代,使用标记-复制算法

Parallel Scavenge 收集器

Parallel工作于新生代,使用标记-复制算法,也是能够并行收集的多线程收集器。Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值,即:

parallel是如何控制吞吐量的?

核心策略:自适应调节(Ergonomics)

Parallel Scavenge 内部有一个自动优化系统:

🔹 JVM 会根据运行情况,动态调整年轻代大小晋升阈值GC 频率, 来实现你指定的目标吞吐量或停顿时间

例如:

JVM 就会自动做类似的事情:

  1. 如果 GC 停顿时间太长 → 减小年轻代;

  2. 如果 GC 太频繁(吞吐量低)→ 增大年轻代;

  3. 如果对象晋升过快 → 调整晋升阈值;

  4. 如果 GC 周期太短或太长 → 动态平衡内存布局。

Serial Old 收集器

Serial Old 是 Serial 收集器的老年代版本,使用标记-整理算法,它同样是一个单线程收集器。这个收集器的主要意义也是供客户端模式下的HotSpot虚拟机使用。如果在服务端模式下,它也可能有两种用途:一种是在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用(效果不是很好),另外一种就是作为CMS收集器发生失败时的后备预案,在并发收集发生Concurrent Mode Failure时使用。

Parallel Old 收集器

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

CMS收集器

JDK1.5时引入,JDK9被标记弃用,JDK14被移除

主打获取最短回收停顿时间(Stop The World),工作于老年代,基于标记-清除算法(混合标记-整理),整个过程分为四个步骤:

  1. 初始标记(CMS initial mark)

  2. 并发标记(CMS concurrent mark)

  3. 重新标记(CMS remark)

  4. 并发清除(CMS concurrent sweep)

G1收集器

从JDK9开始,G1垃圾收集器成为了默认的垃圾收集器

G1是一款主要面向服务端应用的垃圾收集器。在G1收集器出现之前的所有其他收集器,包括CMS在内,垃圾收集的目标范围要么是整个新生代 (Minor GC),要么就是整个老年代(Major GC),再要么就是整个Java堆(Full GC)。 而G1跳出了这个樊笼,它可以面向堆内存任何部分来组成回收集(Collection Set,一般简称CSet)进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。

G1 不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、 Survivor 空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理

Region 中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。每个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待。

G1收集器之所以能建立可预测的停顿时间模型,是因为它将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个Java堆中进行全区域的垃圾收集。更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX:MaxGCPauseMillis 指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region。

G1 收集器有以下细节:

每个Region都有自己的记忆集,这些记忆集会记录下别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围之内,用于解决跨代引用问题

通过原始快照 解决 并发标记阶段 线程与用户线程同时进行 带来的 对象引用关系改变问题

  • 三种GC模式,Young GC、Mixed GC和Full GC

    • 当Eden区的内存空间不够新对象的内存分配时,触发Young GC,采用标记-复制算法

    • Mixed GC 是指回收年轻代的 Region 以及一部分老年代中的 Region。Mixed GC 和 Young GC 一样,采用标记-复制算法。当需要分配对象到 Humongous 区域或者堆内存的空间占比超过 -XX:G1HeapWastePercent 设置的 InitiatingHeapOccupancyPercent 值时,G1 会触发一次 concurrent marking,它的作用就是计算老年代中有多少空间需要被回收,当发现垃圾的占比达到 -XX:G1HeapWastePercent 中所设置的 G1HeapWastePercent 比例时,在下次 Young GC 后会触发一次 Mixed GC。

    • Full GC

G1过程:

  • 初始标记:仅仅只是标记一下GC Roots能直接关联到的对象, 并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的 Region 中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿

  • 并发标记:从 GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象

  • 最终标记:对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的原始快照(SATB)记录

  • 筛选回收:负责更新 Region 的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计 划,可以自由选择任意多个Region 构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。

可以看到,除了并发标记,其它阶段都需要暂停用户线程,G1并非纯粹追求低延迟,而是要做到延迟可控

ZGC收集器:

JDK11推出

与G1一样,ZGC也采用基于Region 的堆内存布局,但与它们不同的是,ZGC的Region具有动态性——动态创建和销毁,以及动态的区域容量大小。

  • 小型Region:容量固定为 2MB,用于放置小于256KB的小对象

  • 中型Region:容量固定为32MB,用于放置大于等于256KB但小于4MB的对象

  • 大型Region:容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象,大型Region在ZGC的实现中是不会被重分配(重分配是ZGC的一种处理动作,用于复制对象的收集器阶段)的,因为复制一个大对象的代价非常高昂。

ZGC收集器有一个标志性的设计是它采用的染色指针技术,染色指针是一种直接将少量额外的信息存储在指针上的技术

Linux下64位指针的高18位不能用来寻址,但剩余的46位指针所能支持的64TB内存在今天仍然能够充分满足大型服务器的需要。鉴于此,ZGC的染色指针技术继续盯上了这剩下的46位指针宽度,将其高4位提取出来存储四个标志信息。通过这些标志位,虚拟机可以直接从指针中看到其引用对象的三色标记状态、是否进入了重分配集(即被移动过)、是否只能通过finalize()方法才能被访问到。由于这些标志位进一步压缩了原本就只有46位的地址空间,也直接导致ZGC能够管理的内存不可以超过4TB(2的42次幂)

ZGC不通过原始快照或增量更新来实现并发标记,而是通过染色指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值