从CMS到G1

  在JDK14中CMS已经不再支持CMS了。

  像青春的逝去般的垃圾回收器也迎来了他的换代。

  我们不能龟缩不前,JDK8已经开始展示出颓态。5G的到来以及高端硬件的降价,用户的需求都在告诉我们。要么改变,要么被淘汰。

   本文主要讲解G1回收器和他对比CMS的优劣。其实在JDK11后 8G以上内存99%的场景下 G1都比CMS表现更为优秀。

   G1 内存模型 对比CMS 和之前的 垃圾收集器有了很大的改变。这无疑是惊艳的。

从上图可以看出G1把堆内存划分为若干个区域(Region),我们可以指定region 的大小但必须是2^n 

Eden取默认初始化时堆的5%,新增了Hunmongous用来存储大对象

G1算法上实现了分代 但是物理中已经不再分代了。(个人感觉分代还是比较优秀的理念特别适合于我们这种朝生夕死对象很多的Java程序。ZGC没有分代,或许是他的目标内存太大了不需要或许是底层算法太复杂了 暂时无法实现吧。)

G1的Region是可以相互转换的 也就是 现在是E  将来可能 S O H or null,

CMS 底层回收算法是标记清除。

G1     实现是复制算法(本质上减少了内存碎片,网络上好多人说是因为划分成了很多个Region所有减少内存碎片。这无疑是不准确的。划分成Region只是可以更好的实现复制算法,如果采用标记清除依旧会有大量内存碎片。)

G1     是允许浮动垃圾存在的,在最大执行时间的范围内 会优先收集性价比 比较高的地方。

G1 和CMS 都采用了三色算法 详细的 可以看我的

垃圾收集器介绍和ParNew&CMS与底层三色标记算法详解---必看

 CMS 采用的是增量更新:

增量更新(Incremental update),只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象 的字段里,那就把这个白对象变成灰色的。即插入的时候记录下来。

G1 采用的是原始快照:

增量更新(Incremental update),只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象 的字段里,那就把这个白对象变成灰色的。即插入的时候记录下来。

上图:G1 混合式就近原则处理存活对象

       G1 运做过程:

       G1 常用调优基本参数:

          使用G1 :-XX:+UseG1GC  (GDK11默认就是哦)

          堆的大小: -Xmx32g

           最大停顿时间:-XX:MaxGCPauseMillis=200 (默认就是200 毫秒  别作死调到10  根据需求和硬件环境设定。其实200还好吧。)

           设置的 G1 区域(Region)的大小:-XX:G1HeapRegionSize=n(值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根据最小的 Java 堆大小划分出约 2048 个区域)

           设置 STW 工作线程数的值:-XX:ParallelGCThreads=n(默认等于CPU核数不推荐改哦)

           并行标记的线程数:XX:ConcGCThreads=n

           触发标记周期的 Java 堆占用率阈值:默认占用率是整个 Java 堆的 45%

            The original G1 paper: Detlefs, D., Flood, C., Heller, S., and Printezis, T. 2004. Garbage-first garbage collection. In Proceedings of the 4th international Symposium on Memory Management (Vancouver, BC, Canada, October 24 – 25, 2004)