CMS GC 新生代默认是多大?

点击上方"涤生的博客",关注我

转载请注明原创出处,谢谢

如果读完觉得有收获的话,欢迎加关注

问题

首先抛个问题给大家,看下面 JVM 参数配置:

-Xmx2g -Xms2g -XX:+UseConcMarkSweepGC

猜一猜按照这样的 JVM 参数配置,YoungGen(新生代)是多大呢? 你一定会觉得这还不简单吗,NewRatio 默认为 2,也就是 YoungGen 与 OldGen(老年代)的比例是 1:2,那 YoungGen 大小应该是 2048M/3 = 672M。 真的是这样吗?jmap -heap pid 看看640?wx_fmt=png

然而结果居然是 332.75M(说明下案例中的 JDK 版本是 7)。

分析

要想知道原因,只能撸源码了。 我们从 Arguments(是用来解析 JVM 参数)类的 setcmsandparnewgc_flags 函数说起,看函数名也知道是对 CMS 和 ParNew GC 的参数设置。640?wx_fmt=png

看提示 1,在 MaxNewSize 和 NewRatio 都是默认配置时,MaxNewSize 值为 preferredmaxnewsize,而 preferredmaxnewsize 是什么呢? 看提示 2,alignsizeup 主要是字节对齐用的,可以不用关系细节,所以 preferredmaxnewsize 主要取决于 preferredmaxnewsizeunaligned, 再看提示 3,preferredmaxnewsize_unaligned 的值为

MIN2(max_heap/(NewRatio+1), ScaleForWordSize(young_gen_per_worker * parallel_gc_threads))

,也就是取 maxheap/(NewRatio+1) 和 ScaleForWordSize(younggenperworker * parallelgcthreads) 中较小的那个,max_heap/(NewRatio+1) 这个我们都了解,就是按照 NewRatio 来计算,ScaleForWordSize 又是什么呢?我们来看下 ScaleForWordSize 的定义:640?wx_fmt=png

因为这里我们是 64 位的机器,所以看上面的那行,alignsizedown_ 这个也是字节对齐的,所以 ScaleForWordSize 返回值约为 (x) * 13 / 10,也就是 younggenperworker * parallelgcthreads * 13 / 10 。因此,我们再看看 younggenperworker 和 parallelgcthreads 的取值,而 younggenperworker = CMSYoungGenPerWorker, CMSYoungGenPerWorker 在另一块代码中有定义,跟硬件相关,x86 机器为 64M;而 parallelgcthreads 的值呢? parallelgc_threads = (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),所以我们得看 ParallelGCThreads 的设置640?wx_fmt=png

可知,ParallelGCThreads 在没有设置的情况下会设置成 parallelworkerthreads 函数返回值,我们接着看 parallelworkerthreads 函数:640?wx_fmt=png

再看 calcparallelworker_threads 函数:640?wx_fmt=png

在看 nofparallelworker_threads 函数:640?wx_fmt=png

根据上面三个函数,ParallelGCThreads 最终由 nofparallelworker_threads 函数计算出,其中 ncpus 是 cpu 的核数,测试机器是 4 核,所以 ncpus 为 4,按照上面的公式计算,因此, ParallelGCThreads 为 4。

所以绕了半天,ScaleForWordSize 的值大约是 64M * 4 * 13 / 10 = 332.8M,再做下对齐就得到 332.75M 了;max_heap / (NewRatio+1) 的值为2048M / 3 = 672M,而新生代的值取了较小的 ScaleForWordSize,故为 332.75M。

总结

看到上面的过程,是不是有点奔溃。YoungGen 的大小在没有设置的情况下是通过计算得出的,其大小可能与 NewRatio 的默认配置没什么关系而与ParallelGCThreads 的配置有一定的关系。 那么既然 YoungGen 大小有不确定性,我们最好还是通过这些 -XX:NewSize、-XX:MaxNewSize 或者 -xmn 参数设置下,免得遇到一些奇怪的 GC,让你措手不及。

 

喜欢本文的朋友们,欢迎长按下图关注订阅号涤生的博客,收看更多精彩内容

640?wx_fmt=jpeg

往期精彩

高吞吐低延迟 Java 应用的 GC 优化
再次剖析 “一个 JVM 参数引发的频繁 CMS GC”

一个 JVM 参数引发的频繁 CMS GC

一次 Young GC 的优化实践(FinalReference 相关)

Service Mesh 了解吗?

依赖包滥用System.gc()导致的频繁Full GC

服务框架之注册中心,你不知道的内幕

服务框架的技术栈

PhantomReference导致CMS GC耗时严重

长连接和心跳的那些事儿

ThreadLocal实现原理详解

WeakHashMap垃圾回收原理

System.gc() 源码解读

Long Polling长轮询详解

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值