一、CMS
image.png我们常规熟悉的垃圾收集器逻辑分三个区域分别 新生代(包含三个区域 Eden/S0/S1区域)、老年代(old)、永久代(P区域)。
而在于JDK7之前我们一直使用的是CMS垃圾收集器、JDK8及以上都使用G1垃圾收集器。那他们本质上有什么区别?
我觉得最核心的还是ROI的问题,就是如何把收益最大化、我们都知道垃圾收集器有Top the world 问题,就是垃圾收集期间有停顿问题,不管CMS、G1都有这样的问题,但是CMS停顿是不可精准预测,也就是你不知道他会停顿多久。本质上就是说在CMS GC期间,他需要把用户线程都停下来;对内存对象进行标记清理。
在我们系统使用CMS一般优化就是内存不够用就调大一些、在极端业务场景的情况下;可能会根据业务场景来设置堆大小,比如调小可能GC的频率高;但是RT降低了;调大虽然GC频率低了、但每次触发RT 也提高了。
但一般业务场景是可以接受GC造成的停顿耗时;所以会在宿主机内存可用的情况下还是去调大内存,如果调小的话;对象回收不了也很容易造成内存溢出、风险更大。
二、G1
G1 逻辑上区域还是一样的。新生代(包含三个区域 Eden/S0/S1区域)、老年代(old) 但是他的结构发生了巨大的变化;就是说他把内存分为2048个内存块;每个块的大小在[1M,32M]之间。
image.png
分成块的目的是可以控制扫描范围、这是G1核心功能;你可以设置y每次GC的最大毫秒数、G1根据你设置的毫秒数来决定每次去回收多少个region 块。
-
G1的优点就是更灵活了、GC耗时可配置;最大可能降低了扫描范围,虽然也有STW问题;但是他先圈了一块region再去回收(有限使用比较多的region区域)。 更精细、延迟更低了,也没有垃圾碎片的问题;不像CMS那样每次还要STW整个堆区域;还有垃圾碎片的问题。
-
但是G1 GC的频率更高了。对CPU使用也比较频繁;因为每次GC的区域比较小。
-
CMS GC耗时不可预测、CPU使用率低、在能够容忍GC STW还是不错的选择,还有就是G1的新版对STW的优化可能要收费。
很多细节懒得写,可以看看以下连接。
参考:
https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html
https://plumbr.io/handbook/garbage-collection-algorithms-implementations#serial-gc
https://zhuanlan.zhihu.com/p/52841787
https://github.com/sunwu51/notebook/blob/master/19.09/java_jvm%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8.md
网友评论