先来看一张图,串行代表两个垃圾回收器按顺序执行,并行代表同时执行。STW代表工作线程暂停,Stop The World的意思。

垃圾回收器 执行顺序 执行方式 作用区域 使用算法 说明
Serial GC 串行 工作线程暂停,单线程进行垃圾回收 新生代 复制算法
Serial Old GC 串行 工作线程暂停,单线程进行垃圾回收 老年代 标记-整理算法
ParNew GC 并行 工作线程暂停,多线程进行垃圾回收 新生代 复制算法 Serial GC的多线程版
CMS GC 并行 用户线程和垃圾回收线程同时执行 老年代 标记-清除算法 低暂停
Parallel GC 并行 工作线程暂停,多线程进行垃圾回收 新生代 复制算法 和ParNew相比能动态调整内存分配情况JDK8默认
Parallel Old GC 并行 工作线程暂停,多线程进行垃圾回收 老年代 标记整理算法 替代串行的Serial Old GC
G1 并行 用户线程和垃圾回收线程同时执行 整堆 分区算法 在延迟可控的情况下尽可能提高吞吐量JDK9默认
ZGC 并行 用户线程和垃圾回收线程同时执行 整堆 分页算法 STW的时间不超过1ms,且不会随着堆的大小增加而增加

常用命令:

-XX:+PrintCommandLineFlags,查看使用的垃圾收集器

-XX:+UseSerialGC,指定使用Serial GC处理新生代,并且默认会使用Serial Old GC处理老年代

-XX:+UseParNewGC,指定新生代使用ParNew GC,-XX:+UseConcMarkSweepGC,指定老年代使用CMS GC

-XX:+UseParallelGC,指定新生代使用Parallel GC,-XX:+UserParallelOldGC,指定老年代使用Parallel Old GC,这两个配置一个,另一个自动激活

1. Serial GC、Serial Old GC

Serial GC和Serial Old GC是比较早的垃圾回收器,那个时候一般的服务器CPU还只有一核,所以一个线程进行垃圾回收就够了。串行的意思就是两个垃圾回收器不能同时执行。

2. Parallel GC、Parallel Old GC

Parallel GC进行垃圾回收时也会暂停用户线程(STW),与Serial GC的不同就是它时多线程进行垃圾回收的。下面画个图方便理解垃圾回收过程。

在一次垃圾回收过程中,会进行一次STW,并且会有多个线程同时进行垃圾回收,回收完后用户线程回复运行。

3. CMS GC

CMS全称是ConcMarkSweep,即并发标记清除。但是它不是某个JDK默认的,要使用的话就加上-XX:+UseConcMarkSweepGC参数。

CMS GC是Java9之前我们很常用的垃圾回收器,是针对老年代的使用标记-清除算法的垃圾回收器。我们一般会使用CMS GC替代默认的老年代垃圾回收器,因为CMS GC的特点是低暂停。实现低暂停的方法是在初始标记阶段只标记GC Roots直接可达的对象,这个阶段比较短,所以对用户线程来说是低暂停。

下面用一张图展示它的垃圾回收过程:

阶段一,初始标记:

  • STW,暂停所有用户线程。
  • 然后标记GC Roots直接可达的对象,就是第一层对象。
  • 一旦标记完就恢复用户线程继续执行。
  • 这个阶段很快。

阶段二,并发标记:

  • 从上一个阶段标记出的对象,开始遍历整个老年代,标记出所有的可达对象。
  • 耗时虽然比较长,但好在不需要STW,可与用户线程一起执行。
  • 采用的是三色标记算法(大家自行拓展)。

阶段三,重新标记:

  • 由于在并发标记阶段,应用程序线程也在运行,可能会导致一些对象的状态发生变化,例如新的对象被创建或旧的对象被删除。
  • 为了修正这些问题,需要进行一次短暂的停顿,重新检查并更新标记状态
  • 这个阶段也是“Stop-The-World”的,但也不会太长。

阶段四,并发清理:

  • 清除垃圾对象,释放空间供后续分配使用。
  • 清理工作与应用程序线程并发进行,不会引起停顿。

阶段五,并发重置:

  • CMS收集器会准备下一次垃圾回收循环,重置内部数据结构等。
  • 这一阶段也是与应用程序并发进行的。

CMS整个垃圾回收过程更长了,但是STW的时间变短了,而且在垃圾回收过程中大部分时间用户线程可以执行,所以用户体验更好了。

在并发清理过程中,可能用户线程会产生新的垃圾,这些就是“浮动垃圾”,只能等到下一次GC时来清理。

如果在并发标记、并发清理过程中,用户线程产生的新对象要进入老年代,但是老年代空间又不够,那么就会导致“concurrent mode failure”,此时就会利用Serial Old来做一次垃圾回收,就会做一次全局STW。

由于采用的是标记-清除算法,所以会产生内存碎片,可以通过参数 -XX:+UseCMSCompactAtFullCollection 让JVM在执行完标记-清除后再做一次整理,也可以通过 -XX:CMSFullGCsBeforeCompaction 来指定多少次GC后来做整理,默认是0,表示每次GC后都整理。

CMS垃圾回收器能够在大多数时间内与应用程序并发执行,减少了因垃圾回收引起的停顿时间。然而,CMS也有一些缺点,比如它可能产生大量的浮动垃圾(floating garbage),并且在某些情况下仍然会导致较长的停顿。随着Java版本的发展,G1 GC和ZGC等更先进的垃圾回收器逐渐取代了CMS的地位。

4. G1(Garbage-First)

G1垃圾回收器是在 Java 7 update4 之后引入,并在Java 9中成为默认的垃圾收集器的。G1的设计目标是提供高吞吐量的同时,实现可预测的暂停时间,特别适合处理大堆内存的应用场景。下面介绍一些G1垃圾回收器的内存结构。

先看张图:

之前我们讲的垃圾回收器把堆内存分为Eden、S0、S1、老年代这四个区域,每个区域都是连续的。而在G1中,整块堆内存被分成2048个大小相等的region,这些region在物理上不要求是连续的,但在逻辑上是连续的。每个region可以独立地作为Eden、Survivor或老年代的一部分。所以说G1还是把内存分为了Eden、Survivor、老年代区,只不过空间可以是不连续的了。

Humongous区是专门用来存放大对象的(如果一个对象大小超过了一个region的50%,那么就是大对象)

用一张图展示垃圾回收过程:

阶段一,初始标记:

  • 短暂的STW。
  • 标记出直接可达对象。

阶段二,并发标记:

  • 并发遍历整个堆,标记所有可达对象。
  • 不需要STW。
  • 三色标记。

阶段三,最终标记:

  • 这也是一个较短的STW。
  • 修正并发标记期间由于应用程序运行而可能产生的误差。

阶段四,筛选回收:

  • 需要STW,来清除垃圾对象。
  • 可通过 -XX:MaxGCPauseMillis 来指定GC的STW停顿的时间,所以可能并不会回收掉所有的垃圾对象,默认为200ms(略小于人的平均反应速度)。
  • 由于回收时间有限,所有会选择更有回收价值(垃圾更多)的区域进行回收。这也是Garbage-First(垃圾优先)的名字由来。
  • 采用的是复制算法,不会产生碎片(会把某个region里的可达对象移动到空白的region里)。

由于筛选回收阶段的STW时间可能不够用导致垃圾约积越多,为了避免OOM,G1 中还提供了另外三种垃圾回收模式:Young GC、Mixed GC 和 Full GC,它们有各自的触发条件。

Young GC: Eden区满,就会触发G1的YoungGC,对Eden区进行垃圾回收。

Mixed GC: 老年代的占用率达到了 -XX:InitiatingHeapOccupancyPercent 指定的百分比,回收所有的新生代以及部分老年代,以及大对象区。

Full GC: 在进行Mixed GC的过程中,采用的是复制算法,如果没有空的region可用,就会触发Full GC,会STW,并采用单线程来进行标记-整理算法进行GC,相当于一次Serial GC。

《JVM第9课》垃圾回收器的更多相关文章

  1. 深入理解JVM(五)——垃圾回收器

    轻松学习JVM(五)——垃圾回收器 上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中, ...

  2. [JVM 相关] Java 新型垃圾回收器(Garbage First,G1)

    回顾传统垃圾回收器 HotSpot 垃圾收集器实现 Serial Collector(串型收集器) 使用场景,大多数服务器是单核CPU. 适用收集场景:1. 新生代收集(Young Generatio ...

  3. 深入理解JVM虚拟机3:垃圾回收器详解

    JVM GC基本原理与GC算法 Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Java深受大家欢迎的众多特性之一,能够帮助程 ...

  4. JVM学习第二天(垃圾回收器和内存分配策略)大章

    说道垃圾回收器大家应该都会有所了解,GC白,当然说道具体的可能就不是很清楚了,今天我们就来玩一玩; GC要做的事情: 第一步:确定堆中需要回收的对象; 第二步:什么时候回收; 第三步:怎样回收 为什么 ...

  5. JVM——垃圾收集算法及垃圾回收器

    一.垃圾回收算法 1.标记-清除算法 1)工作流程 算法分为"标记"和"清除"阶段:首先标记出所有需要回收的对象(标记阶段),在标记完成后统一回收所有被标记的对 ...

  6. JVM学习总结三——垃圾回收器

    整两天再看调优分析的部分,发现实际运行环境下,还是要考虑配置垃圾回收器,所以这里就加一小章介绍一下. 首先来看一下HotSpot所支持回收期的关系图: 图中可以看到一共有7中垃圾回收器,以中间绿线为界 ...

  7. JVM(五)垃圾回收器的前世今生

    全文共 2195 个字,读完大约需要 8 分钟. 如果垃圾回收的算法属于内存回收的方法论的话,那本文讨论的垃圾回收器就属于内存回收的具体实现. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器 ...

  8. jvm默认的并行垃圾回收器和G1垃圾回收器性能对比

    http://www.importnew.com/13827.html 参数如下: JAVA_OPTS="-server -Xms1024m -Xmx1024m -Xss256k -XX:M ...

  9. Hotspot JVM垃圾回收器

    前两篇<JVM入门——运行时数据区><JVM常见垃圾回收算法>所提到的实际上JVM规范以及常用的垃圾回收算法,具体的JVM实现实际上不止一种,有JRockit.J9等待,当然最 ...

  10. java虚拟机入门(五)- 常见垃圾回收器及jvm实现

    上节讲完了垃圾回收的基础,包括java的垃圾是什么,如何寻找以及常用的垃圾回收算法,那么那么多的理论知识讲完了,具体是什么样的东西在做着回收垃圾的事情呢?我们接下来就好好聊聊jvm中常用的垃圾回收器. ...

随机推荐

  1. 智能指针相关:enable_shared_from_this()在开发中的常见应用

    类中使用shared_ptr()的问题 当我们先定义一个指针,然后再用这个指针构造两个智能指针 int main() { int* pt = new int(); std::shared_ptr< ...

  2. MySQL数据库基本操作包括MySQL过程、MySQL声明

    MySQL数据库 操纵数据库 查看数据库 show databases; 创建数据库 create database <database_name>; 删除数据库 drop databas ...

  3. 为什么说 Swoole 是 PHP 程序员技术水平的分水岭?

    大家好,我是码农先森. 谈到这个话题有些朋友心中不免会有疑惑,为什么是 Swoole 而不是其他呢?因为 Swoole 是基于 C/C++ 语言开发的高性能异步通信扩展,覆盖的特性足够的多,有利于 P ...

  4. ThinkPHP 6 + PHP7.4.3nts +nginx 使用mysql和oracle数据库

    ThinkPHP 6 + PHP7.4.3nts +nginx 使用mysql和oracle数据库. 前言 业务需求,之前使用的php 7.3.4nts ,mysql自己写的代码,需要对接第三方系统, ...

  5. Mac 打开软件提示‘“xxx”已损坏,无法打开。您应该将它移到废纸篓。’解决方法

    产生错误的原因是软件没有签名.使用下面的命令给软件签名就好了. sudo xattr -rd com.apple.quarantine /Applications/xxx.app

  6. 自制 ShareLaTeX 镜像

    Overleaf 官方的 sharelatex 镜像的 TeX Live 版本可能较旧,无法安装最新的宏包,并且往往只包含了少量的基础宏包.为了方便使用,我们可以自己构建一个使用最新 TeX Live ...

  7. maven 打包 pom build

    <dependencyManagement> <dependencies> <dependency> <groupId>org.springframew ...

  8. WPF 实现一个吃豆豆的Loading加载动画

    运行的效果如下 先引入一下我们需要的库 在nuget上面搜一下"expression.Drawing",安装一下这个包 我们再创建一个Window,引入一下这个包的命名空间 我们设 ...

  9. Identity – Options

    前言 上一篇已经有写到一些配置了, 但不完整, 这里专门写一篇吧. 防暴力登入 services.Configure<IdentityOptions>(options => { // ...

  10. Java 8 新特性:Stream 流快速入门

    前言 在 java 中,涉及到对数组.集合等集合类元素的操作时,通常我们使用的是循环的方式进行逐个遍历处理,或者使用 stream 流的方式进行处理. 什么是 Stream? Stream(流)是一个 ...