基础 | JVM - [JVM 调优]

§1 JVM 调优目的与指标

JVM 调优的指标有 3 个

  • 吞吐量:用户代码运行时间/总运行时间
  • 暂停时间:工作线程被暂停的时间
  • 内存占用:占用的堆的大小

其实上面指标只说了两个事:让 JVM 多干活 & 让 JVM 少占资源
但这两个事实际上是互斥的。
吞吐量降低其实就是因为暂停时间变长,暂停时间变长是为了 GC。GC 是为了收拾 JVM 干活过程中产生的垃圾,那么当然 JVM 可用的空间越小越需要频繁的收拾。

通常,我们认为 JVM 调优的目的是使

  • 吞吐量:
  • 单次 Minor GC < 200ms
  • 单次 Full GC < 5s

§2 常见涉及参数

内存大小五件套
-Xmx:最大堆内存,
-Xms:最小堆内存(初始值),需要和最大内存保持一致,否则可能刚启动 JVM 就频繁 Full GC 扩容,极端情况下堆可能不能扩展到最大值
-Xmn:年轻代大小
-Xms:栈大小,默认 1M,通常不变。
-XX:MetaspaceSize:元空间大小,通常不设置

堆内存主要估值方法有两种:

  • 用 JVM 可用最大内存估算:堆占 2/3 系统内存,新生代占 1/3 堆
  • 用 JVM 实际运行数据估算:主要依赖发生过 Full GC 后老年代的大小为指标

推荐使用第二种,因目前项目部署多实用容器化部署,硬件资源多数不是一个 JVM 独占

-Xms 在线程变量极大的情况下可以调大,反之可以调小(一般 项目中保留 256K 足够使用)。
调小此参数的另一个意义在于可以使 JVM 开辟更多的线程。但是,按传统线程估算方式,最大不过 2N,且线程过多后切换线程上下文的开销也很客观,因此如无特殊需要不没必要特意为了这个原因去调整。

推荐的配置方式

  • 部署服务,进行压测,记录 Full GC 发生后老年代的稳定大小 x
  • 老年代大小需要 2-3 倍 x
  • 新生代大小需要 1-1.5 倍 x
  • 元空间大小事动态向操作系统申请的,建议不设置
  • 综上:
    • -Xmx == -Xms == 3-4 x
    • -Xmn == 1-1.5 x
    • -Xss 保持默认
    • -XX:MetaspaceSize 保持默认

线上问题填坑必备系列
-XX:+HeapDumpOnOutOfMemoryError:堆 oom 后输出 dump 文件
-XX:HeapDumpPath:dump 文件的输出路径

内存比例系列
-XX:SurvivorRatio:eden 相对于当个 survivor 区的大小

其他通用参数
-XX:PreTenuringThreshold:大对象阈值

GC 手搓
-XX:DisableExplicitGC:禁用 System.gc()生产环境开启(开启就是禁用)

GC 打印系列
-XX:+PrintGC:打印 GC 基本信息
-XX:+PrintGCDetails:打印 GC 详细信息
-XX:+PrintHeapAtGC:GC 发生后打印堆信息
-XX:+PrintGCTimeStamps:在 GC 上打印时间戳
-XX:+PrintGCApplicationConcurrentTime:打印应用程序时间
-XX:+PrintGCApplicationStorppedTime:打印暂停时长

此系列参数一般在生产环境上都禁止,因为会影响性能
但可以在测试环境中开启,发生线上问题准备复现时也可以在沙箱中开启

Flags 系列
-XX:+PrintFlagsInitial:打印 JVM 参数的初始化值
-XX:+PrintFlagsFinal:打印 JVM 参数的最终应用值

Parallel 系列
-XX:+UseParallelGC:启用 Parallel 垃圾回收新生代,一般启用并行老年代会关联开启并行新生代
-XX:+UseParallelOldGC:启用 Parallel 垃圾回收
-XX:ParallelGCThreads:并行 GC 的线程数,一般等于核数
-XX:+UseAdaptiveSizePolicy:是否自动选择各区大小比例,一般不启用

CMS 系列
-XX:+UseConcMarkSweepGC:是否启用 CMS
-XX:ParallelGCThreads:初始标记阶段并行 GC 的线程数,默认 8
-XX:CMSInitiatingOccupancyFraction:使用多少比例后开始 CMS 收集,默认 2/3,需要在实际环境中根据现象调整

  • 值过小:会频繁 GC
  • 值过大:可能导致 CMS 收集失败,触发兜底的 SerialOld 收集器导致卡顿

-XX:+UseCMSCompactAtFullCollection:Full GC 时压缩
-XX:CMSFullGCsBeforeCompaction:几次 Full GC 后启用压缩

  • 想使用此参数,-XX:+UseCMSCompactAtFullCollection 必须开启
  • 配置 0 表示 1 次 FullGC 后压缩,与配置 1 一样

-XX:GCTimeRatio:GC 时间占程序运行时间比例,一般不使用
会导致强制终止 GC,所以不推荐
-XX:MaxGCPauseMillis:最大 GC 停顿毫秒值,一般不使用
此配置会使 JVM 用各种方法向这个指标考虑,甚至可能减小年轻代,导致神器的问题

-XX:CMSClassUnloadingEnabled:启用类卸载,默认开启,一般不更改
-XX:CMSInitiatingPermOccupancyFraction:什么比例时开始进行永久代 GC,jdk1.8之后无效

G1 系列
-XX:+UseG1GC:是否启用 G1
-XX:G1HeapRegionSize:单个 region 大小,1-32M

  • 应按 1、2、4、8、16、32 逐级增大
  • 默认 1/2048 堆
    • 官方推荐 G1 内存 > 6G
    • G1 内存开辟具有优先级,元空间 > 老年代 > 新生代
    • 因此若内存太小可能导致新生代几乎无空间,开辟到新生代时已经不够用了
  • region 变大后,GC 间隔会变长,同时 GC 时间、垃圾生存时间都会变长

-XX:G1NewSizePercent:最小新生代比例,一般不使用
-XX:G1MaxNewSizePercent:最大新生代比例,默认 60%

-XX:MaxGCPauseMillis:最大 GC 停顿毫秒值
这个参数几乎可以说和 -XX:G1NewSizePercent 互斥,因为 G1 可以满足配置的最大停顿时间就是通过 region 角色的灵活切换,但 -XX:G1NewSizePercent 直接限制了 region 的角色
这两个参数对比,通常保留使用 -XX:MaxGCPauseMillis
-XX:GCPauseIntervalMillis:GC 间隔时间
-XX:MaxGCPauseMillis-XX:GCPauseIntervalMillis 参数没有配置时,G1 会用 -XX:G1NewSizePercent & -XX:G1MaxNewSizePercent 参数为依据自动调整

-XX:GCTimeRatioGC:GC 时间占程序运行时间比例,一般不使用
会导致强制终止 GC,所以不推荐
-XX:ConcGCThreads:并行 GC 线程数
-XX:InitiatingHeapOccupancyPercent默认 45%,目前已经开辟为 region 的内存,使用多少比例后触发开辟新的 region

§3 其他参数

TLAB 系列
-XX:+UseTLAB:默认开启的,TLAB 可以辅助减小线程并发访问堆中对象
-XX:+PrintTLAB:打印 TLAB 使用情况
-XX:TLABSize:设置 TLAB 大小

分代年龄
-XX:MaxTenuringThreshold:最大分代年龄,默认 15(CMS 中是 6),一般不动

相关推荐

  1. 基础 | JVM - [JVM ]

    2024-03-11 10:38:05       31 阅读
  2. jvm 参数

    2024-03-11 10:38:05       27 阅读
  3. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      39 阅读
  4. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      34 阅读
  5. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      42 阅读
  6. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      42 阅读
  7. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      42 阅读
  8. <span style='color:red;'>JVM</span><span style='color:red;'>调</span><span style='color:red;'>优</span>

    JVM

    2024-03-11 10:38:05      36 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-11 10:38:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-11 10:38:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-11 10:38:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-11 10:38:05       18 阅读

热门阅读

  1. Spring MVC ViewNameMethodReturnValueHandler原理解析

    2024-03-11 10:38:05       22 阅读
  2. linux后台启动命令

    2024-03-11 10:38:05       22 阅读
  3. npm run dev(pnpm run dev) 的过程都做了什么?

    2024-03-11 10:38:05       23 阅读
  4. c语言:倒序4位数

    2024-03-11 10:38:05       22 阅读
  5. 【Docker】Neo4j 容器化部署

    2024-03-11 10:38:05       21 阅读
  6. 机器学习的要素及步骤

    2024-03-11 10:38:05       21 阅读
  7. 【Linux的网络编程】

    2024-03-11 10:38:05       21 阅读
  8. leetcode 第388场周赛第二题

    2024-03-11 10:38:05       23 阅读
  9. 【二分算法】借教室

    2024-03-11 10:38:05       20 阅读
  10. 【C/C++ 学习笔记】指针

    2024-03-11 10:38:05       24 阅读