关于java:难顶面试官问我G1垃圾收集器

3次阅读

共计 3847 个字符,预计需要花费 10 分钟才能阅读完成。

面试官 要不这次来聊聊 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 面试,对线面试官系列继续更新中!

【对线面试官 - 挪动端】系列 一周两篇继续更新中!
【对线面试官 - 电脑端】系列 一周两篇继续更新中!

原创不易!!求三连!!

正文完
 0