Skip to content

Commit

Permalink
Update CMS
Browse files Browse the repository at this point in the history
  • Loading branch information
flycash committed Jun 21, 2021
1 parent e873951 commit a1e6107
Showing 1 changed file with 29 additions and 0 deletions.
29 changes: 29 additions & 0 deletions gc/java_cms.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit a1e6107

Please sign in to comment.