CMS默认新生代是多大(转)

看下面这段JVM参数
-Xmx2g -Xms2g -XX:+UseConcMarkSweepGC

这样的JVM参数配置,新生代多大呢?NewRatio 默认为2,也就是新生代与老年代的比例是1:2,那新生代大小应该是2048M/3= 672M。真的是这样吗?

通过  jmap 查看JVM堆内存
要说具体原因只能撸源码了。
我们从 Arguments(是用来解析JVM参数)类的 set_cms_and_parnew_gc_flags 这个方法说起,看方法名也知道是对 cms 和 parnew GC 方式的参数设置。
MaxNewSize 设置

可以看到里面有段 MaxNewSize 的设置(提示1),在 MaxNewSize 和 NewRatio 都是默认配置时,MaxNewSize 值为 preferred_max_new_size,preferred_max_new_size 这又是什么呢?(提示2),align_size_up 主要是字节对齐用的,可以不用关心细节,所以 preferred_max_new_size 主要取决于 preferred_max_new_size_unaligned。

再看提示3,preferred_max_new_size_unaligned 的值为 MIN2(max_heap/(NewRatio+1), ScaleForWordSize(young_gen_per_worker * parallel_gc_threads)),也就是取 max_heap/(NewRatio+1) 和 ScaleForWordSize(young_gen_per_worker * parallel_gc_threads) 中较小的那个,max_heap/(NewRatio+1) 这个我们都了解(NewSize大小),ScaleForWordSize 又是什么呢?

这里我们是64位的,align_size_down_ 这个也是字节对齐的,所以 ScaleForWordSize 返回值约为(x) * 13 / 10,也就是 young_gen_per_worker * parallel_gc_threads * 13 / 10

所以我们再看看 young_gen_per_worker 和 parallel_gc_threads 的取值:young_gen_per_worker = CMSYoungGenPerWorker,CMSYoungGenPerWorker 在另一块代码中有定义,跟硬件相关x86机器为64M。而 parallel_gc_threads 的值呢?parallel_gc_threads =(ParallelGCThreads == 0 ? 1 : ParallelGCThreads),所以我们得看 ParallelGCThreads。
ParallelGCThreads 在没有设置的情况下会设置成 parallel_worker_threads 方法返回值,我们接着看 parallel_worker_threads 方法。

看上图1,2,3最终由3进行计算,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
既然新生代大小有不确定性,最好还是手动设置下 -XX:NewSize、 -XX:MaxNewSize,免得遇到一些奇怪的GC。

转自 简书 涤生

Tags:,

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

4 − 4 =