【JVM】图解垃圾收集器1

前言

如果说收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者。本文主要介绍六种经典垃圾收集器用到哪些回收算法?适用哪些场景?

在这里插入图片描述

Serial收集器

Serial收集器是最基础、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是HotSpot虚拟机新生代 收集器的唯一选择。

Serial收集器回收过程如下图所示:

在这里插入图片描述

特点:

  • Serial收集器属于新生代 收集器,单线程执行垃圾回收,必须全程冻结用户线程的运行。
  • 收集算法是使用 标记-复制算法。因为新生代的对象特性:绝大部分对象的存活时间很短,很快就被回收。
  • 垃圾回收不是频繁发生的场景下,单线程没有线程交互的开销,可以更加高效的进行垃圾回收。例如:运行在 Client模式 下的虚拟机,Serial收集器 是很好的选择。

ParNew收集器

ParNew收集器实质上是Serial收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之 外,其余的行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX: PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The
World
、对象分配规 则、回收策略等都与Serial收集器完全一致,在实现上这两种收集器也共用了相当多的代码。

ParNew收集器回收过程如下图所示:
在这里插入图片描述

特点:

  • ParNew收集器是许多运行在 Server模式 下的虚拟机中首选的新生代收集器,除了Serial收集器外,目前只有它能与 CMS收集器 配合工作。

  • 在多核的场景下,ParNew收集器 相比 Serial收集器更有效率。而且,随着CPU的数量增加,ParNew收集器 的垃圾回收效率呈正比增加。

  • 自JDK 9开始,ParNew加CMS收集器的组合就不再是官方 推荐的服务端模式下的收集器解决方案了。还取消了ParNewSerial Old以及SerialCMS这两组收集器组合的支持,并直接取消了- XX:+UseParNewGC参数,这意味着ParNew和CMS从此只能互相搭配使用

Parallel Scavenge收集器

Parallel Scavenge收集器是新生代收集器,同样使用标记-复制算法,也是并行的执行垃圾回收,执行垃圾回收的过程必须全程冻结用户线程的运行。与ParNew最大的不同,它并不关注如何尽可能地缩短垃圾回收时用户线程的冻结时间,它关注的是垃圾回收的吞吐量。

Parallel Scavenge收集器回收过程如下图所示:
在这里插入图片描述吞吐量公式:

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

特点:

用户线程冻结的时间越短,越适合进行用户交户的程序,快速的响应速度是良好用户体验的基本条件。高吞吐量意味着高效率地利用CPU时间,更快地完成程序的运算任务,因此Parallel Scavenge收集器 适合应用在隐藏在后台运行的运算任务。

Serial Old收集器

Serial OldSerial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。

特点:

  • Serial Old收集器 的主要意义跟 Serial收集器 一样,在于给 Client模式 下的虚拟机使用。
  • 如果在 Server模式 下,那么它主要还有两大用途:一种用途是在JDK 1.5以及之前的版本中与 Parallel Scavenge收集器 搭配使用,另一种用途就是作为 CMS收集器 的后备预案,在并发收集发生 Concurrent Mode Failure 时使用。

Concurrent Mode Failure发生场景:

1.在执行 CMS GC 的过程中同时用户线程将对象放入老年代,而此时老年代空间不足,这时 CMS 还没有机会回收老年代产生的。

2.在做 Minor GC 的时候,新生代的 Survivor 区 放不下,需要放入老年代,而老年代也放不下而产生的。

Parallel Old收集器

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

CMS收集器

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

CMS收集器回收过程如下图所示:
在这里插入图片描述

整个过程分为四步:

  1. 初始标记(initial mark),单线程执行,需要 Stop The World,但仅仅把 GC Roots 的直接关联可达的对象给标记一下,由于直接关联对象比较小,所以这里的速度非常快。

  2. 并发标记(concurrent mark),对于初始标记过程所标记的初始标记对象,进行并发追踪标记,此时其他线程仍可以继续工作。此处时间较长,但不停顿。

  3. 重新标记(remark),在并发标记的过程中,由于可能还会产生新的垃圾,所以此时需要重新标记新产生的垃圾。此处执行并行标记,与用户线程不并发,所以依然会”Stop The World”,时间比初始标记要长一点。

  4. 并发清除(concurrent sweep),并发清除之前所标记的垃圾。其他用户线程仍可以工作,不需要停顿。

整个过程中最耗费时间的并发标记与并发清除阶段,用户线程和垃圾回收线程可以并发执行,因此整体的垃圾回收效率是低停顿的。

缺点:

  1. 标记-清除算法会产生内存碎片。

  2. CMS收集器 的并发能力依赖于CPU资源。

  3. CMS收集器无法处理浮动垃圾,可能出现 Concurrent Mode Failure 失败而导致另一次Full GC的产生。

标记-清除算法 会产生内存碎片,为什么不替换成其他算法?

当执行并发清除的时候,标记-压缩算法将会整理内存碎片,导致用户线程使用的内存空间发生位移,用户线程出错。为了保证用户线程能继续执行,前提条件是运行的资源不受影响。因此标记-清除算法更加合适。

G1收集器

详见:
https://blog.csdn.net/qq_35764295/article/details/126538045

小结

在这里插入图片描述

在这里插入图片描述
点赞 收藏 关注
我曾难自拔于世界之大,也沉迷于其中梦话。

猜你喜欢

转载自blog.csdn.net/qq_35764295/article/details/126578955