JVM知识梳理(三) JVM常见垃圾回收器解析

本文介绍了JVM中的垃圾回收器,包括Serial、ParNew、ParallelScavenge等多种类型,并详细解析了G1垃圾回收器的特点及新发展的ZGC垃圾回收器。

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

前言

什么是垃圾回收器?

之前我们介绍过JVM的垃圾回收算法,标记-清除、标记-压缩、复制算法,都是逻辑上能够实现的一些理论,而垃圾回收器就是这些算法的具体实现方案,真正回收垃圾也就是垃圾回收器,不同的JDK版本默认使用的垃圾回收器也存在不同

常见的垃圾回收器有哪些?

共7个,Serial垃圾收集器、Serial Old垃圾收集器、ParNew垃圾收集器、Parallel Scavenge垃圾收集器、Parallel Old垃圾收集器、CMS垃圾收集器、G1垃圾收集器。

如何查看当前JDK版本的垃圾回收器是什么?

可以在启动Java程序时,启动的Edit Configuration中,填入VM option

-XX:+PrintCommandLineFlags

笔者是Java8,可以看到默认的垃圾回收器是ParallelGC。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0fthBVuU-1611738216869)(C:\Users\Sunny-Boy\AppData\Roaming\Typora\typora-user-images\1611674567033.png)]

垃圾收集器的组合

在分别介绍7种垃圾回收器之前,我们要知道,这些垃圾回收器,有的是针对堆空间年轻代的,有的是针对堆空间老年代的。

通过下图可以看到,Serial GC可以与CMS GC搭配,也可以与Serial Old GC搭配,其他也是一样的,有连线代表是可搭配,目前只需要有这样一个组合概念,后面会介绍各垃圾收集器。

需要额外注意的是G1垃圾回收器,它既能为年轻代工作,又能为老年代工作。

下面我们分别介绍一下各种垃圾回收器,首先我们要了解STW机制是什么

STW即Stop the world,是在垃圾回收时,必须暂停所有工作线程,直到收集完成。

效果表现为一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互。

Serial垃圾收集器

Serial收集器是针对新生代的,采用复制算法,采用串行回收方式,是虚拟机在client级别默认新生代的GC方式,利用STW机制方式执行垃圾回收。

Serial Old垃圾收集器

Serial Old收集器是针对老年代的,采用标记压缩算法,是Serial收集器的老年代版本,与Serial收集器类相同的是,它也采用串行回收方式和STW机制,是虚拟机在client级别默认老年代GC方式。

除此之外,在Server模式下,与新生代的Parallel Scavenge配合使用,同时作为老年代CMS收集器(CMS稍后介绍)的后备方案。

注:可以通过-XX:+UseSerialGC来强制指定Serial 收集器进行GC。相当于新生代使用Serial,老年代使用Serial Old。一般在Java web程序中也不会使用该串行收集器。
ParNew垃圾收集器

针对新生代,采用的是复制算法,是serial回收器的多线程版本,是并行回收方式,所以在多核CPU环境下有着比Serial更好的表现,但是在单CPU情况下,并不比serial性能好,同时,与Serial一样,采用STW机制。

注:可用-XX:+UseParNewGC来指定使用Parallel收集器,用-XX:ParallelGCThreads=X来指定线程数,默认使用与CPU核数相同的线程数。
Parallel Scavenge垃圾收集器

并行收集器,采用复制算法,追求高吞吐量,高效利用CPU,亦是STW机制。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。是server级别默认采用的GC方式,

Parallel Old垃圾收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,采用标记-压缩算法,亦是STW机制,并行收集器,吞吐量优先。

注:可用-XX:+UseParallelGC来指定使用Parallel收集器.
可用-XX:+UseParallelOldGC来指定使用Parallel Old收集器,
可用-XX:ParallelGCThreads=X来指定线程数。一般当CPU核数小于8,则设置与核数相同,否则设置为3+5*num/8,是Java 8 默认的GC回收器
CMS垃圾收集器—老年代GC

CMS(Concurrent Mark Sweep),从英文名称可以看出来,它其实是采用标记-清除算法的,表现为高并发、低停顿,追求最短GC回收停顿时间,在收集过程中既会存在GC线程与工作线程并发工作的时候,也会有存在STW机制的过程,表现为CPU占用比较高,但响应时间快,停顿时间短,是多核cpu 追求高响应时间的选择。CMS在JDK9中标记为废弃,并在JDK14中移除。

工作原理主要分为以下几步

  • 初始标记(STW initial mark):标记出GC Roots能直接关联到的对象。所有的工作线程会暂停,即STW机制,不过这个过程很短暂。
  • 并发标记(Concurrent marking) 从GC Roots的直接关联对象,开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,与垃圾收集线程一起并发运行,这个阶段没有STW机制。
  • 重新标记(STW remark) 在并发标记阶段,事实上会因用户程序继续运作导致标记产生变动,所以需要重新标记。
  • 并发清理(Concurrent sweeping):清理删除掉标记阶段标记的对象
  • 并发重置(Concurrent reset): 这个阶段主要是重置CMS收集器的数据结构,以等待下一次垃圾回收。

注:可用-XX:+UseConcMarkSweepGC 来指定使用CMS垃圾收集器。
缺点
  • 浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随着程序运行⾃然就会有新的垃圾不断产生,这部分垃圾出现的标记过程之后,CMS⽆法在当次收集中处理掉它们,只好留待下⼀次GC中再清理。这些垃圾就是“浮动垃圾”。
  • 采用标记-清除算法,所以不可避免会产生内存碎片。而之所以不使用标记-压缩算法来避免产生内存碎片,是因为在标记-压缩中,会整理内存空间单元,但是要注意CMS收集器是有并发过程的,是有工作线程在同时执行的,譬如并发清理阶段,这时是不能整理内存空间单元的。
  • 存在并发过程,所以需要更多的CPU资源
  • CMS的另一个缺点是它需要更大的堆空间。这是因为CMS标记阶段应用程序的线程还是在执行的,堆空间会有继续分配的情况,为保证在CMS回收完之前还有空间分配给正在运行的应用程序,必须预留一部分空间,如果预留的内存空间无法满足程序需要,那么会出现一次“Concurrent Mode Failure”失败,这时会临时使用Serial Old收集器。综上所述,其实CMS不会在老年代满的时候才开始收集,而是会尝试更早的开始收集,从而避免上面提到的情况,默认当老年代使用68%的时候,CMS就开始行动了。
  • 可用– XX:CMSInitiatingOccupancyFraction =n 来设置这个阀值。
G1垃圾收集器

详见https://tech.meituan.com/2016/09/23/g1.html

G1(Garbage-First)是JDK9中默认的垃圾收集器,官方给G1设定的目标是在延迟可控的情况下,获得尽可能高的吞吐量

G1的思想是区域分代化,即避免在整个Java堆中进行全区域的垃圾收集,而是尽量优先回收垃圾最大量的区间(G1把内存划分为一个个区间,即Region),所以Garbage-First我们也可以理解为垃圾优先的意思。

简单来讲,是实际以Region来分区,逻辑上区分年轻代、年老代、H区。

多出来的这个H区是专门用于存放巨型对象(达到一个Region容量的50%以上)

其他的垃圾回收器会把这样的巨型对象直接放到年老代,当这个巨型对象是短期存活的话,就会频繁触发年老带GC。

如果一个H区装不下巨型对象,那么G1会寻找连续的H分区来存储,如果寻找不到连续的H区的话,就不得不启动 Full GC 了。

在这里插入图片描述

特点
  • 整体上来看是标记-整理算法,局部上看是复制算法。
  • 并行与并发:G1是兼具并行与并发的。
  • 分代收集:把堆空间分为一个个Region,内存回收基本单位是Region,不再要求连续的年轻代、老年代,而是逻辑上有年轻代和老年代。
  • 空间整合:把堆空间分为一个个Region,内存回收基本单位是Region,Region之间是复制算法,整体G1垃圾回收是标记压缩,相对于CMS都能避免内存碎片问题
  • 可预测的停顿时间模型:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒
垃圾回收器的新发展一(ZGC垃圾回收器)

在尽可能对吞吐量影响不大的情况下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在10ms以下,工作过程

  • 并发标记
  • 并发预备重分配
  • 并发重分配
  • 并发重映射、

ZGC很快,官方发布的测试数据如下:

  • max-JOPS:吞吐量
  • critical-JOPS:要求延迟的吞吐量

ZGC在JDK14之前,只能在Linux环境下使用。

除了Oracle官方发布的ZGC外,其他厂商,比如阿里也有自定义实现的AliGC,AliGC是基于G1算法,提出的面向大堆的垃圾收集器。

参考

https://www.cnblogs.com/bootdo/p/10482853.html
https://www.bilibili.com/video/BV1PJ411n7xZ?p=183
https://blog.csdn.net/a745233700/article/details/121724998?spm=1001.2014.3001.5502

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值