难顶!面试官问我G1垃圾收集器
面试官:要不这次来聊聊G1垃圾收集器?
候选者:嗯嗯,好的呀
候选者:上次我记得说过,CMS垃圾收集器的弊端:会产生内存碎片&&空间需要预留
候选者:这俩个问题在处理的时候,很有可能会导致停顿时间过长,说白了就是CMS的停顿时间是「不可预知的」
候选者:而G1又可以理解为在CMS垃圾收集器上进行"升级"
候选者:G1 垃圾收集器可以给你设定一个你希望Stop The Word 停顿时间,G1垃圾收集器会根据这个时间尽量满足你
候选者:在前面我在介绍JVM堆的时候,是画了一张图的。堆的内存分布是以「物理」空间进行隔离
候选者:在G1垃圾收集器的世界上,堆的划分不再是「物理」形式,而是以「逻辑」的形式进行划分
候选者:不过,像之前说过的「分代」概念在G1垃圾收集器的世界还是一样奏效的
候选者:比如说:新对象一般会分配到Eden区、经过默认15次的Minor GC新生代的对象如果还存活,会移交到老年代等等...
候选者:我来画下G1垃圾收集器世界的「堆」空间分布吧
候选者:从图上就可以发现,堆被划分了多个同等份的区域,在G1里每个区域叫做Region
候选者:老年代、新生代、Survivor这些应该就不用我多说了吧?规则是跟CMS一样的
候选者:G1中,还有一种叫 Humongous(大对象)区域,其实就是用来存储特别大的对象(大于Region内存的一半)
候选者:一旦发现没有引用指向大对象,就可直接在年轻代的Minor GC中被回收掉
面试官:嗯...
候选者:其实稍微想一下,也能理解为什么要将「堆空间」进行「细分」多个小的区域
候选者:像以前的垃圾收集器都是对堆进行「物理」划分
候选者:如果堆空间(内存)大的时候,每次进行「垃圾回收」都需要对一整块大的区域进行回收,那收集的时间是不好控制的
候选者:而划分多个小区域之后,那对这些「小区域」回收就容易控制它的「收集时间」了
面试官:嗯...
面试官:那我大概了解了。那要不你讲讲它的GC过程呗?
候选者:嗯,在G1收集器中,可以主要分为有Minor GC(Young GC)和Mixed GC,也有些特殊场景可能会发生Full GC
候选者:那我就直接说Minor GC先咯?
面试官:嗯,开始吧
候选者:G1的Minor GC其实触发时机跟前面提到过的垃圾收集器都是一样的
候选者:等到Eden区满了之后,会触发Minor GC。Minor GC同样也是会发生Stop The World的
候选者:要补充说明的是:在G1的世界里,新生代和老年代所占堆的空间是没那么固定的(会动态根据「最大停顿时间」进行调整)
候选者:这块要知道会给我们提供参数进行配置就好了
候选者:所以,动态地改变年轻代Region的个数可以「控制」Minor GC的开销
面试官:嗯,那Minor GC它的回收过程呢?可以稍微详细补充一下吗
候选者:Minor GC我认为可以简单分为为三个步骤:根扫描、更新&&处理 RSet、复制对象
候选者:第一步应该很好理解,因为这跟之前CMS是类似的,可以理解为初始标记的过程
候选者:第二步涉及到「Rset」的概念
面试官:嗯...
候选者:从上一次我们聊CMS回收过程的时候,同样讲到了Minor GC,它是通过「卡表」(cart table)来避免全表扫描老年代的对象
候选者:因为Minor GC 是回收年轻代的对象,但如果老年代有对象引用着年轻代,那这些被老年代引用的对象也不能回收掉
候选者:同样的,在G1也有这种问题(毕竟是Minor GC)。CMS是卡表,而G1解决「跨代引用」的问题的存储一般叫做RSet
候选者:只要记住,RSet这种存储在每个Region都会有,它记录着「其他Region引用了当前Region的对象关系」
候选者:对于年轻代的Region,它的RSet 只保存了来自老年代的引用(因为年轻代的没必要存储啊,自己都要做Minor GC了)
候选者:而对于老年代的 Region 来说,它的 RSet 也只会保存老年代对它的引用(在G1垃圾收集器,老年代回收之前,都会先对年轻代进行回收,所以没必要保存年轻代的引用)
面试官:嗯...
候选者:那第二步看完RSet的概念,应该也好理解了吧?
候选者:无非就是处理RSet的信息并且扫描,将老年代对象持有年轻代对象的相关引用都加入到GC Roots下,避免被回收掉
候选者:到了第三步也挺好理解的:把扫描之后存活的对象往「空的Survivor区」或者「老年代」存放,其他的Eden区进行清除
候选者:这里要提下的是,在G1还有另一个名词,叫做CSet。
候选者:它的全称是 Collection Set,保存了一次GC中「将执行垃圾回收」的Region。CSet中的所有存活对象都会被转移到别的可用Region上
候选者:在Minor GC 的最后,会处理下软引用、弱引用、JNI Weak等引用,结束收集
面试官:嗯,了解了,不难
面试官:我记得你前面提到了Mixed GC ,要不来聊下这个过程呗?
候选者:好,没问题的。
候选者:当堆空间的占用率达到一定阈值后会触发Mixed GC(默认45%,由参数决定)
候选者:Mixed GC 依赖「全局并发标记」统计后的Region数据
候选者:「全局并发标记」它的过程跟CMS非常类型,步骤大概是:初始标记(STW)、并发标记、最终标记(STW)以及清理(STW)
面试官:确实很像啊,你继续来聊聊具体的过程呗?
候选者:嗯嗯,还是想说明下:Mixed GC它一定会回收年轻代,并会采集部分老年代的Region进行回收的,所以它是一个“混合”GC。
候选者:首先是「初始标记」,这个过程是「共用」了Minor GC的 Stop The World(Mixed GC 一定会发生 Minor GC),复用了「扫描GC Roots」的操作。
候选者:在这个过程中,老年代和新生代都会扫
候选者:总的来说,「初始标记」这个过程还是比较快的,毕竟没有追溯遍历嘛
面试官:...
候选者:接下来就到了「并发标记」,这个阶段不会Stop The World
候选者:GC线程与用户线程一起执行,GC线程负责收集各个 Region 的存活对象信息
候选者:从GC Roots往下追溯,查找整个堆存活的对象,比较耗时
面试官:嗯...
候选者:接下来就到「重新标记」阶段,跟CMS又一样,标记那些在「并发标记」阶段发生变化的对象
候选者:是不是很简单?
面试官:且慢
面试官:CMS在「重新标记」阶段,应该会重新扫描所有的线程栈和整个年轻代作为root
面试官:据我了解,G1好像不是这样的,这块你了解吗?
候选者:嗯,G1 确实不是这样的,在G1中解决「并发标记」阶段导致引用变更的问题,使用的是SATB算法
候选者:可以简单理解为:在GC 开始的时候,它为存活的对象做了一次「快照」
候选者:在「并发阶段」时,把每一次发生引用关系变化时旧的引用值给记下来
候选者:然后在「重新标记」阶段只扫描着块「发生过变化」的引用,看有没有对象还是存活的,加入到「GC Roots」上
候选者:不过SATB算法有个小的问题,就是:如果在开始时,G1就认为它是活的,那就在此次GC中不会对它回收,即便可能在「并发阶段」上对象已经变为了垃圾。
候选者:所以,G1也有可能会存在「浮动垃圾」的问题
候选者:但是总的来说,对于G1而言,问题不大(毕竟它不是追求一次把所有的垃圾都清除掉,而是注重 Stop The World时间)
面试官:嗯...
候选者:最后一个阶段就是「清理」,这个阶段也是会Stop The World的,主要清点和重置标记状态
候选者:会根据「停顿预测模型」(其实就是设定的停顿时间),来决定本次GC回收多少Region
候选者:一般来说,Mixed GC会选定所有的年轻代Region,部分「回收价值高」的老年代Region(回收价值高其实就是垃圾多)进行采集
候选者:最后Mixed GC 进行清除还是通过「拷贝」的方式去干的
候选者:所以,一次回收未必是将所有的垃圾进行回收的,G1会依据停顿时间做出选择Region数量(:
面试官:嗯,过程我大致是了解了
面试官:那G1会什么时候发生full GC?
候选者:如果在Mixed GC中无法跟上用户线程分配内存的速度,导致老年代填满无法继续进行Mixed GC,就又会降级到serial old GC来收集整个GC heap
候选者:不过这个场景相较于CMS还是很少的,毕竟G1没有CMS内存碎片这种问题(:
本文总结(G1垃圾收集器特点):
- 从原来的「物理」分代,变成现在的「逻辑」分代,将堆内存「逻辑」划分为多个Region
- 使用CSet来存储可回收Region的集合
- 使用RSet来处理跨代引用的问题(注意:RSet不保留 年轻代相关的引用关系)
- G1可简单分为:Minor GC 和Mixed GC以及Full GC
- 【Eden区满则触发】Minor GC 回收过程可简单分为:(STW) 扫描 GC Roots、更新&&处理Rset、复制清除
- 【整堆空间占一定比例则触发】Mixed GC 依赖「全局并发标记」,得到CSet(可回收Region),就进行「复制清除」
- R大描述G1原理的时候,从宏观的角度看G1其实就是「全局并发标记」和「拷贝存活对象」
- 使用SATB算法来处理「并发标记」阶段对象引用可能会修改的问题
- 提供可停顿时间参数供用户设置(G1会尽量满足该停顿时间来调整 GC时回收Region的数量)
欢迎关注我的微信公众号【Java3y】来聊聊Java面试,对线面试官系列持续更新中!
【对线面试官-移动端】系列 一周两篇持续更新中!
【对线面试官-电脑端】系列 一周两篇持续更新中!
原创不易!!求三连!!
难顶!面试官问我G1垃圾收集器的更多相关文章
- 【原创】面试官问我G1回收器怎么知道你是什么时候的垃圾?
这是why技术的第36篇原创文章 上面的图片是我上周末在家拍的.以后的文章里面我的第一张配图都用自己随手拍下的照片吧.分享生活,分享技术,哈哈. 阳台上的花开了,成都的春天快来了,疫情也应该快要过去了 ...
- 面试官,不要再问我“Java 垃圾收集器”了
如果Java虚拟机中标记清除算法.标记整理算法.复制算法.分代算法这些属于GC收集算法中的方法论,那么"GC收集器"则是这些方法论的具体实现. 在面试过程中这个深度的问题涉及的比较 ...
- 面试官,不要再问我“Java 垃圾收集器”了(转载)
如果Java虚拟机中标记清除算法.标记整理算法.复制算法.分代算法这些属于GC收集算法中的方法论,那么"GC收集器"则是这些方法论的具体实现. 在 面试过程中这个深度的问题涉及的比 ...
- java面试-G1垃圾收集器
一.以前收集器的特点 年轻代和老年代是各自独立且连续的内存块 年轻代收集器使用 eden + S0 + S1 进行复制算法 老年代收集必须扫描整个老年代区域 都是以尽可能的少而快速地执行 GC 为设计 ...
- G1 垃圾收集器架构和如何做到可预测的停顿(阿里)
CMS垃圾回收机制 参考:图解 CMS 垃圾回收机制原理,-阿里面试题 CMS与G1的区别 参考:CMS收集器和G1收集器优缺点 写这篇文章是基于阿里面试官的一个问题:众所周期,G1跟其他的垃圾回收算 ...
- G1垃圾收集器的实现原理
(G1垃圾收集器的实现原理.G1和CMS经常被单独拎出来问) https://tech.meituan.com/g1.html G1太复杂,说下CMS吧
- G1垃圾收集器系统化说明【官方解读】
还是继续G1官网解读,上一次已经将这三节的东东读完了,如下: 所以接一来则继续往下读: Reviewing Generational GC and CMS[回顾一下CMS收集器] The Concur ...
- [每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- [每日一题]面试官问:谈谈你对ES6的proxy的理解?
[每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
随机推荐
- [转载]session多服务器共享的方案梳理
转载网址: http://www.cnblogs.com/wangtao_20/archive/2013/10/29/3395518.html session的存储了解以前是怎么做的,搞清楚了来龙去脉 ...
- Python语句,表达式的区别?
参考了网上的文章,说 表达式的结果是值,对象 比如1+2, 是表达式 具体根据运算符不同有算术,逻辑,比较等等类型的表达式 语句是控制程序走向,不产生值 例如if/else等 参考: https:// ...
- 【CTF】msf和impacket联合拿域控内网渗透-拿域控
前言 掌控安全里面的靶场内网渗透,练练手! 内网渗透拿域控 环境:http://afsgr16-b1ferw.aqlab.cn/?id=1 1.进去一看,典型的sql注入 2.测试了一下,可以爆库,也 ...
- 洛谷P6075题解
题面 首先这 \(n\) 个数是互相独立的,所以我们不需要统一的去考虑,只需要考虑其中一个数即可. 我们以 \(k=5\) 的情况举例. 我设 \(f_i\) 为最后一行只填前 \(i\) 个点的情况 ...
- Java-多态(下)
多态 一种类型的多种状态 还有一个小汽车的例子再理解下 汽车接口(相当于父类) package com.oop.demo10; public interface Car { String getNam ...
- 🚴♂️全套MySQL数据库教程_Mysql基础入门教程,零基础小白自学MySQL数据库必备教程☔ #002 # 第二单元 MySQL数据类型、操作表#
二.本单元知识点概述 (Ⅰ)知识点概述 二.本单元教学目标 (Ⅰ)重点知识目标 1.Mysql的数据类型2.如何选择数据类型3.创建表4.修改表5.删除表 (Ⅱ)能力目标 1.熟练创建数据库及删除数据 ...
- 鲲鹏展翅|SphereEx 获华为鲲鹏技术认证
SphereEx Data Middleware 通过了华为鲲鹏技术认证并加入鲲鹏展翅伙伴计划,未来 SphereEx Data Middleware 产品将继续以分布式能力为基础,以数据安全.分布式 ...
- 学习笔记——不带修序列莫队 (luogu2079)小B的询问
莫队是一种对于询问的离线算法 时间复杂度:O(\(n \sqrt n\)) 大致思想就是 首先将询问离线,然后对原序列分块,使得每一个\(l和r\)都在一个块里 然后按照左节点排序,若所在的块相等,就 ...
- Winform同步调用异步函数死锁原因分析、为什么要用异步
1.前言 几年前,一个开发同学遇到同步调用异步函数出现死锁问题,导致UI界面假死.我解释了一堆,关于状态机.线程池.WindowsFormsSynchronizationContext.Post.co ...
- 【机器学习基础】逻辑回归——LogisticRegression
LR算法作为一种比较经典的分类算法,在实际应用和面试中经常受到青睐,虽然在理论方面不是特别复杂,但LR所牵涉的知识点还是比较多的,同时与概率生成模型.神经网络都有着一定的联系,本节就针对这一算法及其所 ...