经典面试题 | 讲一下垃圾回收器都有哪些?

简介: 经典面试题 | 讲一下垃圾回收器都有哪些?

垃圾回收器有哪些?


是一个高频的面试题,那本文就详细来解答这个问题。


因为不同的厂商(IBM、Oracle),实现的垃圾回收器各不相同,而本文要讨论的是 Oracle 的 HotSpot 虚拟机所使用的垃圾回收器。


常用垃圾回收器,如下图所示:


微信图片_20220117180154.png


  • 新生代回收器:Serial、ParNew、Parallel Scavenge
  • 老年代回收器:Serial Old、Parallel Old、CMS
  • 整堆回收器:G1


其中相互连线的垃圾回收器,表示可以相互搭配使用。


新生代 And 老生代


目前常用的商用垃圾收集器都使用的是分代垃圾回收方式。


分代垃圾回收器把内存分为:新生代(Young Generation)和老生代(Tenured Generation),如下图所示:


微信图片_20220117180157.png


(图片来自fancydeepin)


默认情况下,新生代和老生代的内存比例是 1:2,该值可以通过 -XX:NewRatio来设定。


新生代(Young Generation)


程序中的大部分对象都符合“朝生夕死”的特性,所以绝大数新创建的对象都会存放在新生代,除非是大对象会直接进入老生代。新生代采用的是复制算法,这样可以更高效的回收内存空间。


新生代有细分为:Eden、Form Survivor、To Survivor 三个区域,默认的比例是 8:1:1,

可以通过 -XX:SurvivorRatio 来设定。


新生代垃圾回收的执行过程:


1、Eden 区 + From Survivor 区存活着的对象复制到 To Survivor 区;


2、清空 Eden 和 From Survivor 分区;


3、From Survivor 和 To Survivor 分区交换(From 变 To,To 变 From)。


老生代(Tenured Generation)


老生代垃圾回收的频率比新生代低,存放的主要对象是:


1、新生代对象经过 N 次 GC 晋升到老年代。


可以通过设置-XX:MaxTenuringThreshold=5 来设置,默认值是 15 次。


2、大对象直接存储到老生代。


所谓的“大对象”指的是需要连续存储空间的对象,比如:数组。


当大对象在新生代存储不下的时候,就需要分配担保机制,把当前新生代的所有对象复制到老年代中,因为分配担保机制需要涉及大量的复制,会导致性能问题,所有最好的方案是直接把大对象存储到老生代中。


通过参数 -xx:PretrnureSizeThreshold 来设定大对象的值。


注意:该参数只有 Serial 和 ParNew 垃圾回收器有效。


Serial


Serial 最早的垃圾回收器,JDK 1.3.1 之前新生代唯一的垃圾回收器,使用的是单线程串行回收方式,在单 CPU 环境下性能较好,因为单线程执行不存在线程切换。


线程类型: 单线程


使用算法: 复制算法


指定收集器: -XX:+UseSerialGC


Serial Old


Serial 收集器的老年代版本,同样也是单线程的。它有一个实用的用途作为CMS收集器的备选预案,后面介绍CMS的时候会详细介绍。


线程类型: 单线程


使用算法: 标记-整理


指定收集器: -XX:+UseSerialGC


ParNew


ParNew 其实就是 Serial 的多线程版本,可以和 Serial 共用很多控制参数,比如:-XX:SurvivorRatio , ParNew 可以和 CMS 配合使用。


微信图片_20220117180159.png


(注:图片来源于零壹技术栈)


线程类型: 多线程


使用算法: 复制


指定收集器: -XX:+UseParNewGC


Parallel Scavenge


Parallel 和 ParNew 收集器类似,也是多线程的,但 Parallel 是吞吐量优先的收集器,GC停顿时间的缩短是以吞吐量为代价的,比如收集 100MB 的内存,需要 10S 的时间,CMS 则会缩短为 7S 收集 50 MB 的内存,这样停顿的时间确实缩少了,但收集的频率变大了,吞吐量就变小了。


线程类型: 多线程


使用算法: 复制


指定收集器: -XX:+UseParallelGC


Parallel Old


Parallel Old 是 Parallel 的老生代版本,同样是吞吐量优先的收集器。


线程类型: 多线程


使用算法: 标记-整理


指定收集器: -XX:+UseParallelOldGC


CMS


CMS(Concurrent Mark Sweep)一种以获得最短停顿时间为目标的收集器,非常适用B/S系统。


使用 Serial Old 整理内存。


CMS 运行过程:


微信图片_20220117180201.png


(注:图片来源于零壹技术栈)


1、初始标记


标记 GC Roots 直接关联的对象,需要 Stop The World 。


2、并发标记


从 GC Roots 开始对堆进行可达性分析,找出活对象。


3、重新标记


重新标记阶段为了修正并发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World 。


4、并发清除


除垃圾对象。


CMS 缺点:


1、对 CPU 资源要求敏感。


CMS 回收器过分依赖于多线程环境,默认情况下,开启的线程数为(CPU 的数量 + 3)/ 4,当 CPU 数量少于 4 个时,CMS 对用户本身的操作的影响将会很大,因为要分出一半的运算能力去执行回收器线程。


2、CMS无法清除浮动垃圾。


浮动垃圾指的是CMS清除垃圾的时候,还有用户线程产生新的垃圾,这部分未被标记的垃圾叫做“浮动垃圾”,只能在下次 GC 的时候进行清除。


3、CMS 垃圾回收会产生大量空间碎片。


CMS 使用的是标记-清除算法,所有在垃圾回收的时候回产生大量的空间碎片。


注意:CMS 收集器中,当老生代中的内存使用超过一定的比例时,系统将会进行垃圾回收;当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时采用 Serial Old 算法进行清除,此时的性能将会降低。


线程类型: 多线程


使用算法: 标记-清除


指定收集器: -XX:+UseConcMarkSweepGC


G1


G1 GC 这是一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。G1 可以直观的设定停顿时间的目标,相比于 CMS GC,G1 未必能做到 CMS 在最好情况下的延时停顿,但是最差情况要好很多。


G1 GC 仍然存在着年代的概念,但是其内存结构并不是简单的条带式划分,而是类似棋盘的一个个 region。Region 之间是复制算法,但整体上实际可看作是标记 - 整理(Mark-Compact)算法,可以有效地避免内存碎片,尤其是当 Java 堆非常大的时候,G1 的优势更加明显。


微信图片_20220117180204.jpg


G1 吞吐量和停顿表现都非常不错,并且仍然在不断地完善,与此同时 CMS 已经在 JDK 9 中被标记为废弃(deprecated),所以 G1 GC 值得深入掌握。


G1 运行过程:


1、初始标记


标记 GC Roots 直接关联的对象,需要 Stop The World 。


2、并发标记


从 GC Roots 开始对堆进行可达性分析,找出活对象。


3、重新标记


重新标记阶段为了修正并

发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World 。


4、筛选回收


首先对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来制定回收计划。这个阶段可以与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的。


线程类型: 多线程


使用算法: 复制、标记-整理


指定收集器: -XX:+UseG1GC(JDK 7u4 版本后可用)



相关文章
|
1月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
4月前
|
存储 缓存 监控
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
Java面试题:在Java中,对象何时可以被垃圾回收?编程中,如何更好地做好垃圾回收处理?
68 0
|
4月前
|
缓存 监控 算法
Java面试题:描述Java垃圾回收的基本原理,以及如何通过代码优化来协助垃圾回收器的工作
Java面试题:描述Java垃圾回收的基本原理,以及如何通过代码优化来协助垃圾回收器的工作
87 8
|
4月前
|
监控 算法 Java
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
374 4
|
4月前
|
算法 Java
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
58 1
|
4月前
|
存储 监控 算法
Java面试题:解释分代垃圾回收策略,并说明其优势
Java面试题:解释分代垃圾回收策略,并说明其优势
51 0
|
4月前
|
算法 Java 程序员
Java面试题:解释Java的垃圾回收机制,包括常见的垃圾回收算法。介绍一下Java的垃圾回收算法中的标记-压缩算法。
Java面试题:解释Java的垃圾回收机制,包括常见的垃圾回收算法。介绍一下Java的垃圾回收算法中的标记-压缩算法。
49 0
|
4月前
|
设计模式 安全 NoSQL
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
68 0
|
4月前
|
设计模式 安全 Java
Java面试题:请解释Java中的四种访问控制符及其作用范围,请解释Java中的垃圾回收机制及其工作原理,请解释Java中的并发工具包及其主要用途
Java面试题:请解释Java中的四种访问控制符及其作用范围,请解释Java中的垃圾回收机制及其工作原理,请解释Java中的并发工具包及其主要用途
31 0
|
4月前
|
并行计算 安全 算法
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
40 0