面试官:谈谈你对JVM垃圾收集器的了解

简介: 面试官:谈谈你对JVM垃圾收集器的了解

本文默认JVM为HotSpot。之前已经介绍过常见的垃圾收集算法,这次再来说说JVM具体实现了这些算法的垃圾收集器。


下图为HotSpot虚拟机有的垃圾收集器,有连线关系的表示可以搭配使用,反之不能。


image.png

每种垃圾收集器都有各自的特性,我们需要根据不同的场景来使用不同的垃圾收集器。


新生代垃圾收集器


Serial

此垃圾收集器年代久远,用于新生代的垃圾收集,采用复制算法。是单线程的垃圾收集器也就是不管你的服务器有多少CPU,反正它就用其中的一个CPU启动一个线程去处理垃圾回收,并且停止所有工作线程等待它回收完成。所以它在收集时会STW(stop the world)。能与其搭配的老年代收集器是CMS与Serial Old。



image.png

image.png


单线程的好处就在于它简单,没有上下文线程切换的开销。多用于桌面应用中,也就是适用于client模式。因为桌面应用一般占用的内存不大,内存不大代表需要处理的垃圾不多,所以即使单线程也能处理很快,所以感受不到STW。是client模式下默认的新生代垃圾收集器。


ParNew


此垃圾收集器可以说是Serial的多线程版本,它和Serial的差别就在于复制的时候是多线程的。


image.png


它主要是能利用多CPU,提升复制的速度,减少STW的时间。但是在单CPU情况下不要使用它,因为线程切换有开销,性能不一定会比Serial好,当然如果CPU数很多的话那性能肯定是比Serial好的。所以在Server模式下可以用它来作为新生代垃圾处理器。能与其搭配的老年代收集器是CMS与Serial Old。


Parallel Scavenge

Scavenge是捡破烂的意思...恩并行捡破烂说的是好像没错,用的也是复制算法。那不是已经在ParNew了吗,怎么还来个并行的。它和ParNew主要有两个不同点


1、Parallel Scavenge的关注点在于可控制的吞吐量,吞吐量=运行用户代码的时间/(运行用户代码的时间+GC时间)。就是说它的重点不在于想缩短每次GC的时间,而在于控制虚拟机运行一段时间中,所花费在GC上的总时间。比如程序运行了100分钟,其间垃圾收集了1分钟,那吞吐量就是99%。


2、Parallel Scavenge能自适应调节新生代中配置的参数,例如Eden和survivor比例等。其实就是因为它能自适应,所以才能可控制吞吐量,它根据实际情况动态调整这些参数来达到要求的吞吐量。


此收集器也提供了“-XX:MaxGCPauseMillis”控制垃圾收集最大停顿时间(允许值大于0),“-XX:GCTimeRatio”吞吐量(1-99)。 看到“-XX:MaxGCPauseMillis”,别以为我们想设置多少就多少,收集器只能尽可能的保证而已。而且说白了能如果想提高新生代GC的速度,那就是减少新生代的内存空间,内存空间少垃圾肯定少处理起来肯定快。但是空间少是不是更快的容易满啊,所以所需的GC次数肯定会增多,那吞吐量也会下降。

比如说一个程序现在跑在服务器上,假设每次新生代GC时间是100毫秒,每10秒钟一次新生代GC,那一分钟花费在GC上的时间就是600毫秒。那我想每次花在GC时间更少比如60毫秒,那就减少新生代内存空间,但是这样每5秒钟一次GC,那一分钟花费在GC上的时间就是720毫秒。


对应使用的场景就是如果你的服务是计算类的,默默在后台计算,和用户交互很少,所以你肯定想的是吞吐量大,也就是总的GC时间短,能充分的用了CPU来计算,这个时候就适合用Parallel Scavenge。


那如果你的程序是交互类的,你的要求肯定就是STW的时间越短越好,能快速响应客户的请求。Parallel Scavenge也行,但是它不能和CMS联合使用呀!因为Parallel Scavenge没有使用原本HotSpot中和其它GC通用的那个GC框架,而是新框架。所以默认和CMS搭配的就是ParNew。


image.png


老年代垃圾收集器


Serial Old

它是Serial 收集器的老年代版本,是单线程收集,采用的是标记-整理算法。主要用于client模式和CMS的后备收集器。除了G1,上面说的几个新生代收集器都可以与它搭配使用。图请参考上面Serial。


Paraller Old

它是Parallel Scavenge的老年代版本,是多线程收集,采用的是标记-整理算法。它只能和Parallel Scavenge搭配。它的出现打破了Parallel Scavenge尴尬的地位,因为之前Parallel Scavenge只能和Serial Old配合,人家新生代都多线程跑了,奈何老年代只有单线程,拖累它了。图请参考上面Parallel Scavenge。


CMS

CMS(Concurrent Mark Sweep),从名字可以看出它采用的是标记-清除算法。它致力于减少STW的时间,让垃圾收集时同时用户线程也能并行着。在目前的Server主流垃圾收集器。


image.png

它的垃圾收集步骤分为以下4步:

1、初始标记(会STW)

2、并发标记

3、重新标记(会STW)

4、并发清理


初始标记就是仅标记GC Roots直接关联的对象,不继续深入标记,致力于减少STW时间。并发标记就是深入标记遍历后面所有关联对象。重新标记就是修正因并发标记阶段而发生变动了的对象标记会STW。然后就是并发清理垃圾。


所以CMS把所需消耗时间最长的深入标记阶段和清理阶段与用户线程并行。大大减少了STW所需的时间。


但是它有以下3个缺点:


1、并发阶段会与工作线程争抢CPU资源


2、空间碎片问题,因为采取的是标记-清除算法所以会产生空间碎片。为什么解决这个问题CMS提供了"-XX:+UseCMSCompactAtFullCollection"(默认开启),用于当CMS顶不住需要进行FullGC时整理空间碎片,但是整理的过程是用户线程是得停止工作的,所以停顿的时间会变长。


3、浮动垃圾问题。因为在并发清理的时候允许用户线程继续执行,而执行就可能产生新的垃圾进入老年代,所以需要预留一部分空间给这些浮动垃圾,而当这些浮动垃圾过多在CMS运行期间爆了,那CMS就会出现“Concurrent Mode Failure”,这是时候就得后备的Serial Old上来重新进行老年代的垃圾收集,所以停顿的时间就更长了。


G1


此垃圾收集器不需要和别人配合,自己处理新生代和老年代。在jdk9中G1变为Server模式默认的垃圾收集器。它的发明就是为了替代CMS。

G1(Garbage-First)从整体来看是基于标记-整理的算法,从局部来看是基于复制算法。它和CMS一样可以和用户进程并行。相对于CMS 它的优点是首先它能建立可预测的停顿时间模型,能在一个规定的时间段内指定垃圾收集的时间不超过限制的毫秒数,并且它将Java堆分为多个大小相等的独立区域,也就是Region。虽然它还保留着分代的概念,但是新生代和老年代不是物理隔离了。 它的清理区间不再是整个新生代或者老年代,而是以区域为划分,不会产生空间碎片


G1会维护一个优先列表,根据跟踪各个region回收所能产生的空间大小和时间来标定优先级,优先回收优先级最大的Region。这就等于每次的回收目标更加精确化,提高回收的效率 G1的收集步骤可分为:

1、初始标记

2、并发标记

3、最终标记

4、筛选回收



image.png

image.png

初始标记和CMS一样先标记GC Roots直接关联对象,然后并发深入标记,遍历关联对象。最终标记和CMS重新标记一个概念,筛选回收也就是筛选下决定回收哪个Region价值更大。

相关文章
|
11天前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
11天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
1月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
2月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
1月前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
30 4
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
51 2
|
1月前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
1月前
|
存储 缓存 JavaScript
JVM面试真题总结(一)
JVM面试真题总结(一)
|
2月前
|
存储 缓存 监控
【Java面试题汇总】JVM篇(2023版)
JVM内存模型、双亲委派模型、类加载机制、内存溢出、垃圾回收机制、内存泄漏、垃圾回收流程、垃圾回收器、G1、CMS、JVM调优
【Java面试题汇总】JVM篇(2023版)
|
1月前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。
下一篇
无影云桌面