JVM学习(五)垃圾收集器

本文详细介绍了JVM中的各种垃圾收集器,包括Serial、ParNew、ParallelScavenge、SerialOld、ParallelOld、CMS和G1收集器。探讨了它们的算法原理、特点以及适用场景,为理解JVM内存管理和调优提供了全面的视角。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JVM学习(五)垃圾收集器

前言

侵删,记录自学时的笔记

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现

在这里插入图片描述

图 1 JDK1.7 HotSpot虚拟机的垃圾收集器

图1展示了新生代和老年代的垃圾收集器,可以看到不同收集器之间存在连线,被线相连的垃圾收集器可以搭配使用

垃圾收集器

Serial(连续)垃圾收集器(单线程、复制算法)

最基础的收集器,使用复制算法。在JDK1.3.1之前是虚拟机新生代垃圾收集器的唯一选择。这是一个单线程的收集器,它在进行垃圾收集时,必须暂停其他所有的工作线程,直至收集结束。

在这里插入图片描述

图 2 Serial/Serial Old收集器运行示意图

虽然这种“暂停”对很多应用来说难以接受,但它到现在为止,仍然是虚拟机运行在Client模式下默认的新生代收集器对于限定单个CPU的环境来说,Serial收集器没有线程交互的开销,专心做垃圾收集可以获得最高的单线程收集效率

ParNew收集器(Serial+多线程)

Serial收集器的多线程版本(复制算法)。除了多线程进行垃圾收集之外,其余行为几乎与Serial收集器完全一样。事实上,这两种收集器也共用了相当多的代码。

ParNew垃圾收集器在垃圾收集过程中同样也要暂停所有其他的工作线程

在这里插入图片描述

图 3 ParNew/Serial Old收集器运行示意图

Parallel Scavenge收集器(多线程复制算法、高效)

新生代收集器,使用复制算法的收集器,并行的多线程收集器。

与ParNew的区别

Parallel Scavenge收集器的关注点在于达到一个可控制的吞吐量

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

ParNew、CMS等收集器关注点在于尽可能地缩短垃圾收集时用户线程的停顿时间

停顿时间越短越适合需要与用户交互的程序,良好的响应速度能提高用户体验,而高吞吐量可以高效率地利用CPU时间,尽快完成程序的运算任务

与ParNew的重要区别:自适应调节策略:虚拟机根据当前系统的运行情况收集性能监控信息动态调整这些参数(-Xmn 、-XX:SurvivorRatio、-XX:PretenureSizeThreshold)以提供最合适的停顿时间或者最大的吞吐量

-Xmn 新生代的大小

-XX:SurvivorRatio Eden区与Survivor区的比例

-XX:PretenureSizeThreshold 晋升老年代对象年龄

Serial Old收集器(单线程标记整理算法)

Serial收集器老年代版本,单线程收集器,使用标记-整理算法

这个收集器的主要意义也是给Client模式下的虚拟机使用。

在Server模式下主要有两大用途:一种用途是JDK1.5及以前的版本中与Parallel Scavenge收集器搭配使用另一种用途是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用

在这里插入图片描述

图 4 Serial/Serial Old收集器运行示意图

Parallel Old收集器(多线程 标记-整理算法)

Parallel Scavenge收集器的老年代版本,多线程 ,使用标记-整理算法

这个收集器是在JDK 1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直 处于比较尴尬的状态。原因是,如果新生代选择了Parallel Scavenge收集器,老年代除了 Serial Old(PS MarkSweep)收集器外别无选择(还记得上面说过Parallel Scavenge收集器无 法与CMS收集器配合工作吗?)。由于老年代Serial Old收集器在服务端应用性能上的“拖 累”,使用了Parallel Scavenge收集器也未必能在整体应用上获得吞吐量最大化的效果,由于 单线程的老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件比较 高级的环境中,这种组合的吞吐量甚至还不一定有ParNew加CMS的组合“给力”。

直到Parallel Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组 合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old 收集器。

在这里插入图片描述

图 5 Parallel Scavenge/Parallel Old收集器运行示意图

CMS收集器(多线程 标记-清除算法)

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。

CMS收集器基于标记-清除算法实现。整个过程分为4个步骤

初始标记(CMS initial mark)

并发标记(CMS concurrent mark)

重新标记(CMS remark)

并发清除(CMS concurrent sweep)

在这里插入图片描述

图 6 Concurrent Mark Sweep收集器运行示意图

可以看出,初始标记、重新标记仍然会停止其他工作线程

初始标记仅仅标记一下GC Roots能直接关联到的对象速度很快并发标记阶段是进行 GC Roots Tracing的过程,重新标记阶段是为了修正并发标记期间因为用户程序继续运作而导致标记产生变动的那一部分对象的标记记录这一阶段的停顿时间比初始标记阶段稍长,远比并发标记时间短并发清理阶段则是清除GC Roots不可达对象

由于耗时长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作,所以总体上来看 CMS收集器的内存回收和用户线程是一起并发地执行。

CMS的三个缺点
  1. CMS收集器无法处理浮动垃圾。可能导致出现Concurrent Mode Failure而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法 在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”
  2. CMS收集器对CPU资源非常敏感。其实,面向并发设计的程序都对CPU资源比较敏感。 在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说CPU资 源)而导致应用程序变慢,总吞吐量会降低。
  3. 标记-清除算法会产生大量空间碎片,对将来为大对象分配内存造成麻烦。

G1收集器

G1(Garbage-First)收集器是当今收集器技术发展的最前沿成果之一,早在JDK 1.7刚刚 确立项目目标,Sun公司给出的JDK 1.7 RoadMap里面,它就被视为JDK 1.7中HotSpot虚拟机 的一个重要进化特征。从JDK 6u14中开始就有Early Access版本的G1收集器供开发人员实 验、试用,由此开始G1收集器的“Experimental”状态持续了数年时间,直至JDK 7u4,Sun公 司才认为它达到足够成熟的商用程度,移除了“Experimental”的标识。

对比与CMS收集器,G1收集器的两个最突出的改进是:

  1. 基于标记-整理算法,不产生内存碎片
  2. 可以非常精确控制停顿时间在不牺牲吞吐量的前提下,实现低停顿垃圾回收

G1收集器的运作大致可划分为以下几个步骤

  • 初始标记
  • 并发标记
  • 最终标记
  • 筛选回收

G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得高的垃圾收集效率。

在这里插入图片描述

图 7 G1收集器运行示意图

对CMS收集器运作过程熟悉的读者,一定已经发现G1的前几个步骤的运作过程和CMS 有很多相似之处。初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改 TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的 Region中创建新对象,这阶段需要停顿线程,但耗时很短。并发标记阶段是从GC Root开始 对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执 行。而最终标记阶段则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动 的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最 终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行。最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序, 根据用户所期望的GC停顿时间来制定回收计划,从Sun公司透露出来的信息来看,这个阶段 其实也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。

参考资料

《Java虚拟机(第二版)》

JAVA核心面试知识整理.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值