前言
如果说收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者。本文主要介绍六种经典垃圾收集器用到哪些回收算法?适用哪些场景?
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收集器的组合就不再是官方 推荐的服务端模式下的收集器解决方案了。还取消了
ParNew
加Serial Old
以及Serial
加CMS
这两组收集器组合的支持,并直接取消了- XX:+UseParNewGC
参数,这意味着ParNew和CMS从此只能互相搭配使用。
Parallel Scavenge收集器
Parallel Scavenge
收集器是新生代收集器,同样使用标记-复制算法,也是并行的执行垃圾回收,执行垃圾回收的过程必须全程冻结用户线程的运行。与ParNew
最大的不同,它并不关注如何尽可能地缩短垃圾回收时用户线程的冻结时间,它关注的是垃圾回收的吞吐量。
Parallel Scavenge
收集器回收过程如下图所示:
吞吐量公式:
吞吐量 = 运行用户代码时间 /( 运行用户代码时间 + 垃圾收集时间 )
特点:
用户线程冻结的时间越短,越适合进行用户交户的程序,快速的响应速度是良好用户体验的基本条件。高吞吐量意味着高效率地利用CPU时间,更快地完成程序的运算任务,因此
Parallel Scavenge
收集器 适合应用在隐藏在后台运行的运算任务。
Serial Old收集器
Serial Old
是Serial
收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。
特点:
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 Old
是Parallel Scavenge
收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实 现。
CMS收集器
CMS(Concurrent Mark Sweep)
收集器是一种以获取最短回收停顿时间为目标的收集器。
CMS
收集器回收过程如下图所示:
整个过程分为四步:
初始标记(initial mark),单线程执行,需要 Stop The World,但仅仅把 GC Roots 的直接关联可达的对象给标记一下,由于直接关联对象比较小,所以这里的速度非常快。
并发标记(concurrent mark),对于初始标记过程所标记的初始标记对象,进行并发追踪标记,此时其他线程仍可以继续工作。此处时间较长,但不停顿。
重新标记(remark),在并发标记的过程中,由于可能还会产生新的垃圾,所以此时需要重新标记新产生的垃圾。此处执行并行标记,与用户线程不并发,所以依然会”Stop The World”,时间比初始标记要长一点。
并发清除(concurrent sweep),并发清除之前所标记的垃圾。其他用户线程仍可以工作,不需要停顿。
整个过程中最耗费时间的并发标记与并发清除阶段,用户线程和垃圾回收线程可以并发执行,因此整体的垃圾回收效率是低停顿的。
缺点:
标记-清除算法会产生内存碎片。
CMS收集器 的并发能力依赖于CPU资源。
CMS收集器无法处理浮动垃圾,可能出现 Concurrent Mode Failure 失败而导致另一次Full GC的产生。
标记-清除算法 会产生内存碎片,为什么不替换成其他算法?
当执行并发清除的时候,标记-压缩算法将会整理内存碎片,导致用户线程使用的内存空间发生位移,用户线程出错。为了保证用户线程能继续执行,前提条件是运行的资源不受影响。因此标记-清除算法更加合适。
G1收集器
详见:
https://blog.csdn.net/qq_35764295/article/details/126538045
小结
点赞 收藏 关注
我曾难自拔于世界之大,也沉迷于其中梦话。