面试官:说说虚拟机中的七大垃圾收集器吧!(上)

简介: 面试官:说说虚拟机中的七大垃圾收集器吧!(上)


image.png


上面展示了七种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用,下面我将具体的介绍上面的七种垃圾收集器。


不过在介绍之前我要给大家明确一个观点就是:


虽然垃圾收集器的技术在不断进步,但直到现在还没有最好的收集器出现,更加不存在“万能”的收集器,所以我们选择的只是对具体应用最合适的收集器。如果有一种放之四海皆准、任何场景下都适用的完美收集器存在,HotSpot虚拟机完全没必要实现那么多种不同的收集器了。


一、Serial(串行)垃圾收集器


Serial(串行)垃圾收集器是最基本、发展历史最悠久的收集器,在JDK1.3.1前是HotSpot新生代收集的唯一选择。


它是一个单线程工作的收集器,它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束(这个过程也称为 Stop The world,俗称STW)。


下图:Serial/Serial Old收集器运行示意图


image.png


特点


  1. 只作用在新生代
  2. 串行工作有STW现象
  3. 采用复制算法
  4. 简单而高效,是Client模式下默认的垃圾收集器
  5. 对于内存资源受限的环境,它是所有收集器里额外内存消耗(Memory Footprint)最小的。
  6. 对于单核处理器或处理器核心数较少的环境来说,Serial收集器由于没有线程交互(上下文切换)的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。
  7. 可以通过JVM参数-XX:+UseSerialGC设置新生代使用串行垃圾回收器。


二、ParNew收集器


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


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


image.png


在JDK1.7之前,ParNew收集器是新生代的首选,这是为什么呢!


因为除了Serial收集器外,目前只有它能与 CMS 收集器配合工作。


JDK1.5发布时,HotSpot推出了一款真正意义上的可以让垃圾收集器与用户线程同时工作的收集器——CMS收集器。


但是CMS作为一个老年代的垃圾收集器,却是不能与JDK1.4推出来的新生代收集器Parallel Scavenge配合工作,所有就有了老年代使用CMS,新生代就只能选ParNew或者Serial收集器中的一个。


ParNew收集器是激活CMS后的默认新生代收集器。


如果说,ParNew收集器是因为CMS收集器的出现才逐渐让人熟知,那ParNew收集器退出HotSpot虚拟机历史舞台也同样是因为它。


都知道JDK的更新迭代的速度非常快,所以垃圾收集器的技术也是在发生着日新月异的变化,随着更强大的G1垃圾收集器的出现,CMS的时代也成为了历史。


G1是一个面向全堆的收集器,不再需要其他新生代收集器的配合工作。所以自JDK 9开始,ParNew加CMS收集器的组合就不再是官方推荐的服务端模式下的收集器解决方案了。官方希望它能完全被G1所取代,甚至还取消了ParNew加Serial Old以及Serial加CMS这两组收集器组合的支持(其实原本也很少人这样使用),并直接取消了- XX:+UseParNewGC参数,这意味着ParNew和CMS从此只能互相搭配使用,再也没有其他收集器能够和它们配合了。我们也可以理解为从此以后,ParNew合并入CMS,成为它专门处理新生代的组成部分。


特点


  1. 除了多线程外,其余的行为、特点和Serial收集器一样


  1. ParNew收集器在单核心处理器的环境中绝对不会有比Serial收集器更好的效果


  1. 存在线程交互的开销


相关参数:


指定使用CMS后,会默认使用ParNew作为新生代收集:
"-XX:+UseConcMarkSweepGC"
强制指定使用ParNew:   
"-XX:+UseParNewGC"
指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相:
"-XX:ParallelGCThreads"


三、Parallel Scavenge收集器


首先Parallel Scavenge收集器是一款新生代收集器它同样是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器。


Parallel Scavenge收集器关注点是吞吐量(如何高效率的利用CPU)。


CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。


image.png


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


image.png


Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量


控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数

直接设置吞吐量大小的-XX:GCTimeRatio参数


3.1 -XX:MaxGCPauseMillis参数

该参数设定的值是一个大于 0 的毫秒数,收集器将尽力保证内存回收花费的时间不超过用户设定值。


我们也不要过于极端的把值设置的很小,就以为系统的垃圾收集时间会变得更快,垃圾收集停顿时间缩短是以牺牲吞吐量和新生代空间为代价换取的


比如:系统把新生代调得小一些,收集300MB新生代肯定比收集500MB快,但这也直接导致垃圾收集发生得更频繁,原来10秒收集一次、每次停顿100毫秒,现在变成5秒收集一次、每次停顿70毫秒。停顿时间的确在下降,但吞吐量也降下来了。


3.2 -XX:GCTimeRatio参数

改参数设置地是垃圾收集时间占总时间的比率,0<n<100的整数,相当于吞吐量的倒数。


比如:


用户代码运行时间 99


垃圾收集运行时间 1


吞吐量 = 99 / (1 + 99) = 99%


允许最大占用时间比例 = 1 / (1 + 99) = 1%,即最大比例 1%,n = 1


由于与吞吐量关系密切,Parallel Scavenge收集器也经常被称作“吞吐量优先收集器”。


3.3 值得关注的参数-XX:+UseAdaptiveSizePolicy

开启这个参数后,就不用手工指定一些细节参数,如:


新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等。


JVM会根据当前系统运行情况收集性能监控信息,动态调整这些参数,以提供最合适的停顿时间或最大的吞吐量,这种调节方式称为GC自适应的调节策略(GC Ergonomiscs) 。


如果我们对于收集器运作不太了解,手工优化存在困难的话,使用Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成是一个很不错的选择。


我们只需设置好内存数据大小(如"-Xmx"设置最大堆),然后使用"-XX:MaxGCPauseMillis"或"-XX:GCTimeRatio"给JVM设置一个优化目标,那些具体细节参数的调节就由JVM自适应完成,这也是Parallel Scavenge收集器与ParNew收集器一个重要区别。


四、Serial Old收集器


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


运行示意图如上:Serial(串行)垃圾收集器一节中


应用场景


主要用于Client模式;


而在Server模式有两大用途:


在JDK1.5及之前,与Parallel Scavenge收集器搭配使用(JDK1.6有Parallel Old收集器可搭配)。

作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。


五、Parallel Old收集器


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


运行示意图如上:Parallel Scavenge收集器一节中


它是JDK1.6提出,用来代替老年代的Serial Old收集器,特别是在Server模式,多CPU的情况下。


在注重吞吐量以及CPU资源敏感的场景,用Parallel Scavenge加Parallel Old收集器这样"给力"的应用组合,非常有用。


相关设置参数


“-XX:+UseParallelOldGC”:指定使用Parallel Old收集器;


由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。


如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。


感谢您的阅读,十分欢迎并感谢您的关注。


好了,今天的内容到这里就结束了,关注我,我们下期见


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

目录
相关文章
|
6月前
|
存储 缓存 算法
Very Heavy ! Java虚拟机的垃圾回收处理与垃圾收集算法
Very Heavy ! Java虚拟机的垃圾回收处理与垃圾收集算法
50 0
|
4月前
|
存储 算法 安全
Java面试题:Java内存模型及相关知识点深度解析,Java虚拟机的内存结构及各部分作用,详解Java的垃圾回收机制,谈谈你对Java内存溢出(OutOfMemoryError)的理解?
Java面试题:Java内存模型及相关知识点深度解析,Java虚拟机的内存结构及各部分作用,详解Java的垃圾回收机制,谈谈你对Java内存溢出(OutOfMemoryError)的理解?
70 0
|
3月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
3月前
|
安全 Java
虚拟机栈的五道面试题
这篇文章提供了关于Java虚拟机栈的五个面试问题,涉及栈溢出的情况、栈大小调整、栈内存的分配、垃圾回收与虚拟机栈的关系以及局部变量的线程安全性。
|
4月前
|
算法 Java
Java面试题:列举并解释JVM中常见的垃圾收集器,并比较它们的优缺点
Java面试题:列举并解释JVM中常见的垃圾收集器,并比较它们的优缺点
95 3
|
4月前
|
Java UED
Java面试题:描述JVM中垃圾收集的Stop-The-World现象及其影响
Java面试题:描述JVM中垃圾收集的Stop-The-World现象及其影响
52 1
|
5月前
|
监控 算法 Java
深入理解Java虚拟机:垃圾收集机制的奥秘
【6月更文挑战第17天】在Java的世界,垃圾收集(GC)是保持内存健康不可或缺的一环。本文将揭开JVM垃圾收集的神秘面纱,探索其原理、算法及调优策略,帮助开发者更好地理解和掌握这一关键技术,确保Java应用的性能与稳定性。
42 5
|
4月前
|
Java
Java面试题:什么是G1垃圾收集器,它如何改善性能?
Java面试题:什么是G1垃圾收集器,它如何改善性能?
51 0
|
4月前
|
算法 Java 开发者
Java面试题:Java内存探秘与多线程并发实战,Java内存模型及分区:理解Java堆、栈、方法区等内存区域的作用,垃圾收集机制:掌握常见的垃圾收集算法及其优缺点
Java面试题:Java内存探秘与多线程并发实战,Java内存模型及分区:理解Java堆、栈、方法区等内存区域的作用,垃圾收集机制:掌握常见的垃圾收集算法及其优缺点
39 0
|
4月前
|
监控 算法 Java
Java虚拟机垃圾收集机制深度解析
在Java的世界中,垃圾收集是确保内存管理高效运行的关键机制之一。本文将深入探讨Java虚拟机的垃圾收集机制,包括其工作原理、常见的垃圾收集算法以及调优实践。我们将基于最新的研究数据和实验结果,提供对垃圾收集器性能的比较分析,并讨论如何根据不同应用场景进行优化。通过逻辑严密的分析,我们旨在为Java开发者提供实用的指导,以帮助他们更好地理解和掌握这一关键技术。