diff --git a/gc/java_cms.md b/gc/java_cms.md index 0ee2ddb..301627b 100644 --- a/gc/java_cms.md +++ b/gc/java_cms.md @@ -144,6 +144,35 @@ CMS 的面试,大多数时候来说,就是面一下算法的大概流程, - 讨论到操作系统内存管理 - 讨论到指针碰撞 +#### 类似问题 +- 为啥老年代明明还有空闲内存,却触发了 Full GC?碎片太多,找不到足够大的连续的空闲内存;又或者 CMS 预估到接下来这点空闲内存不够了,需要提前触发GC(时间间隔轮询做这种判断) + +### 什么时候会触发 Full GC? + +分析:考察触发 Full GC的点。在 CMS的语境下,则是考察 CMS 触发的时机。一般人的回答都是从promotion failed这种角度,虽然也对,但是不够完整,严格意义上来说,CMS 的触发,有两种方式,一种是定时轮询,判断要不要 GC,一种就是刚才提到的,`promotion failed` 这种不得不触发的时机。前者我们叫做主动触发,后者叫做被动触发。 + +主动触发的面试亮点在于,要阐述清楚,CMS 是如何轮询的,有什么参数可以控制;被动触发则是列举场景。 + +主动式轮询,有一个参数控制时间间隔。而后,老年代使用率达到阈值,触发GC;开启了回收永久代的时候,永久代使用率达到阈值,也触发GC。 + +被动触发其实很容易记住,就是对象尝试分配到老年代的时候,如果发现老年代找不到一个内存来放对象,那么就会触发GC,这个时候都是退化为串行的 Serial GC。 + +答案:CMS 触发时机有两种,主动触发和被动触发。 + +主动触发是指,CMS 会轮询,判断当前是否需要 GC。(基本回答)CMS 会在老年代内存使用达到一个阈值的时候,开始 GC;又或者在开启了回收永久代的时候,永久代内存使用率触发阈值,触发GC。(进阶)还有两个参数`CMSInitiatingOccupancyFraction` 和 `UseCMSInitiatingOccupancyOnly` 都设置了的话,那么 CMS 的阈值就会使用设置的值,否则是使用默认值。(据我了解是会动态调整) + +被动触发,核心在于对象分配到老年代的时候找不到空闲内存来容纳(这时候,可能是充满了碎片,所以没有连续的足够大的内存来容纳,也可能是确实是都用完了)。而对象分配到老年代,就是晋升失败,或者大对象直接分配失败。 + +(后面可以将话题引导到 promotion failed 的后果,就是面试题**CMS 来不及回收老年代会发生什么事情**) + +#### 类似问题 +- CMS 是否回收永久代?CMS 可以用于回收永久代,但是参数得配置开启 +- CMS 什么时候会退化为 Serial GC? + +#### 如何引导 +- 反正讨论到了 CMS,Full GC 都可以聊这个 +- 可以结合 G1 垃圾回收器,来对比两者的触发时机 + ## Reference [Oracle documents - CMS](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html) [Java gc roots](https://help.eclipse.org/2021-06/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Fconcepts%2Fgcroots.html&cp=37_2_3) \ No newline at end of file