• 关于JVM参数-XXSurvivorRatio的理解


    关于JVM参数-XX:SurvivorRatio的理解

    JVM参数中有一个比较重要的参数SurvivorRatio,它定义了新生代中Eden区域和Survivor区域(From幸存区或To幸存区)的比例,默认为8,也就是说Eden占新生代的8/10,From幸存区和To幸存区各占新生代的1/10

    -XX:SurvivorRatio
    
    • 1

    可参考以下计算公式:

    Eden = (R*Y)/(R+1+1)
    From = Y/(R+1+1)
    To   = Y/(R+1+1)
    
    • 1
    • 2
    • 3

    其中:
    R:SurvivorRatio比例
    Y:新生代空间大小

    这里举个例子,如果我们通过设置-Xmn60M来指定新生代分配的空间大小,那么Eden则会分配60M * 0.8 = 48M,Survivor一共分配60M * 0.2 = 12M的内存空间

    下面我们通过实际命令行的演示来验证上面的结果

    启动参数配置
    -Xmn60M
    -XX:SurvivorRatio=8
    -XX:+PrintFlagsFinal
    
    • 1
    • 2
    • 3
    控制台输出
    uintx NewSize         := 62914560    {product}
    uintx MaxNewSize      := 62914560    {product}
    
    • 1
    • 2

    注:这里只列举了部分重要的指标

    可以看到新生代内存大小为62914560B=60M已经生效,因为Eden区和Survivor区的大小使用JVM参数无法在控制台中查到,所以我们借助Java VisualVM中的Visual GC插件来查看具体指标
    在这里插入图片描述
    OK,指标验证已完成!

    参数值分析

    经过上面的测试我们已经大致理解了新生代内存分配的策略,其实到这一步还没有结束,我们还需要搞清楚下面几个问题:

    • Eden和Survivor比例有什么标准或要求吗?
    • 为什么要设置Eden和Survivor的大小比例?

    假设1:Eden区域设置太大

    新生成的对象会被分配在Eden区,Eden空间不足时会触发MinorGC。理想状态下,如果所有对象在这个阶段全部被回收,Eden区域被清空,不会出什么问题。如果GC后还存在一部分幸存的对象,则会被复制到To Survivor区域,此时因为Survivor区域空间太小无法容纳这些对象,结果大部分幸存对象只在进行一次或很少次的GC后就会被移动到老年代,也就是说从某种程度上来讲失去了MinorGC的初衷,这种情况是肯定不被允许的

    假设2:Eden区域设置太小

    接着分析,Eden区域设置太小,意味着其空间很快就会被占满,也就是说增加了新生代的GC次数,而频繁的GC会降低整体JVM性能

    总结

    一般情况下该参数使用默认值即可,除非你在JVM优化领域有着非常丰富的经验。总之,尽可能最小化"短暂对象"移动到老年代的数量,同时最小化年轻代GC的次数和持续时间,要找到适当的折衷方案,首先要了解应用程序中对象年龄的分布情况

  • 相关阅读:
    初识js作用域链
    SD卡使用记录
    Python fileinput模块:逐行读取多个文件
    postgresql中的stringtype=unspecified有什么作用?
    MySQL 学习记录 1
    CMake常用命令(三)set命令
    ctf:kali工具: msfvenom
    LeetCode 164. 最大间距
    【视频图像篇】FastStone Capture屏幕长截图软件
    splay树:hdu4453 Looploop
  • 原文地址:https://blog.csdn.net/m0_67401228/article/details/126565086