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

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


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收集器;


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


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


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


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


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

目录
相关文章
|
存储 Java 程序员
对线面试官:浅聊一下 Java 虚拟机栈?
对于 JVM(Java 虚拟机)来说,它有两个非常重要的区域,一个是栈(Java 虚拟机栈),另一个是堆。堆是 JVM 的存储单位,所有的对象和数组都是存储在此区域的;而栈是 JVM 的运行单位,它主管 Java 程序运行的。那么为什么它有这样的魔力?它存储的又是什么数据?接下来,我们一起来看。
|
存储 算法 Java
虚拟机中的经典垃圾收集器及常用参数解析(Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1)
这里说的经典垃圾收集器,并不是说这些垃圾收集器多么的优秀,因为随着JDK版本的不断更新,新的垃圾收集器越来越多,这些在JDK9及之前使用的垃圾收集器自然就成为了相对经典的版本。说到垃圾收集器,就必须说垃圾收集算法 点击查看垃圾收集算法详解 ,因为垃圾收集算法是收集收集器的方法论,正是因为有了垃圾收集算法,才有了各种各样的垃圾收集器,下面认识下这些经典的垃圾收集器吧。
591 0
虚拟机中的经典垃圾收集器及常用参数解析(Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1)
|
存储 缓存 监控
Java虚拟机:垃圾收集原理和垃圾收集器
Java虚拟机:垃圾收集原理和垃圾收集器
129 0
Java虚拟机:垃圾收集原理和垃圾收集器
|
存储 缓存 算法
面试:精通Java;面试官:来讲一下JVM虚拟机内存模型的最底层原理,必须说详细说清楚,知其所以然。看完后,你还敢在简历上写精通Java吗?
面试:精通Java;面试官:来讲一下JVM虚拟机内存模型的最底层原理,必须说详细说清楚,知其所以然。看完后,你还敢在简历上写精通Java吗?
193 1
面试:精通Java;面试官:来讲一下JVM虚拟机内存模型的最底层原理,必须说详细说清楚,知其所以然。看完后,你还敢在简历上写精通Java吗?
|
算法 安全 Java
【Java 虚拟机原理】垃圾收集器 ( Serial | ParNew | Parallel Scavenge | CMS | Serial Old - MSC | Parallel Old )
【Java 虚拟机原理】垃圾收集器 ( Serial | ParNew | Parallel Scavenge | CMS | Serial Old - MSC | Parallel Old )
289 0
【Java 虚拟机原理】垃圾收集器 ( Serial | ParNew | Parallel Scavenge | CMS | Serial Old - MSC | Parallel Old )
|
存储 算法 Java
携程面试官问我怎么划分 Java 虚拟机内存区域,相见恨晚!
携程面试官问我怎么划分 Java 虚拟机内存区域,相见恨晚!
152 0
携程面试官问我怎么划分 Java 虚拟机内存区域,相见恨晚!
|
缓存 监控 算法
Java虚拟机浅谈——垃圾收集器与内存分配策略
在C语言中,有些由内存需要程序员在代码中进行手动回收,但是在Java中,没有这样的声明式操作。有没有人有去想过,Java到底做了什么可以自动进行垃圾回收呢?Java中的垃圾回收,是一点都不需要程序员关心,万无一失的吗? 本文将从:Jvm中的垃圾收集器和内存分配策略。虚拟机中对已经死亡的对象都有哪些垃圾回收是算法,两部分和大家谈谈Java虚拟机的垃圾收集器与内存分配策略。
6011 0
Java虚拟机浅谈——垃圾收集器与内存分配策略
|
算法 Java
Java虚拟机详解(四)------垃圾收集器
Java虚拟机详解(四)------垃圾收集器目录 1、垃圾收集器种类2、Serial收集器3、ParNew收集器4、Parallel Scavenge收集器5、Serial Old收集器6、Parallel Old收集器7、CMS收集器8、G1收集器9、如何选择垃圾收集器  10、几个名词解释   上一篇博客我们介绍了Java虚拟机垃圾回收,介绍了几种常用的垃圾回收算法,包括标记-清除,标记整理,复制等,这些算法我们可以看做是内存回收的理论方法,那么在Java虚拟机中,由谁来具体实现这些方法呢?   没错,就是本篇博客介绍的内容——垃圾收集器。
889 0
|
算法 Java
深入学习Java虚拟机——垃圾收集器与内存分配策略
推荐书籍《深入理解Java虚拟机》,本文为个人学习笔记,删除一些不必要文字,并加入部分个人理解,日后复习较为简洁易懂
4772 0