侧边栏壁纸
博主头像
lai博主等级

  • 累计撰写 53 篇文章
  • 累计创建 19 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

JVM调优实战

lai
lai
2023-01-10 / 0 评论 / 0 点赞 / 1,407 阅读 / 1,868 字
温馨提示:
本文最后更新于 2023-01-17,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

目的

  1. 更好的回收频率和更短的回收耗时
  2. 更好的内存利用率

调优策略

两个基本原则:

  1. 将转移到老年代的对象数量降到最少。
  2. 减少Full GC的执行时间。目标是Minor GC时间在100ms以内,Full GC时间在1s以内。

主要调优参数:

  1. 设定堆内存大小,这是最基本的。
    1. -Xms:启动JVM时的堆内存空间。
    2. -Xmx:堆内存最大限制。
    3. 一般将Xms与Xmx设置成相同大小避免扩容时消耗性能
  2. 设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代。
  3. -XX:NewRatio:新生代和老年代的占比。
  4. -XX:NewSize:新生代空间。
  5. -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比。
  6. -XX:MaxTenuringThreshold:对象进入老年代的年龄阈值。
  7. 设定垃圾回收器
    年轻代:-XX:+UseParNewGC。
    老年代:-XX:+UseConcMarkSweepGC。

调优设置

依据Java Performance推荐公式

  1. Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
  2. 永生代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍(JDK8从已经将永生代迁到元数据区)。
  3. 年轻代Xmn的设置为老年代存活对象的1-1.5倍。
  4. 老年代的内存大小设置为老年代存活对象的2-3倍。

调优步骤

触发FullGC

使用jmap 触发FullGC,对生产有一定影响,建议先将服务下线或者空闲时间执行,避免gc对业务造成影响

jmap -histo:live <pid>

打印每个class的实例数目,内存占用,类全名信息.live子参数加上后,只统计活的对象数量. 此时会触发FullGC

查看老年代大小

jmap -heap <pid>

FullGC前

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4213178368 (4018.0MB)
   NewSize                  = 88080384 (84.0MB)
   MaxNewSize               = 1404043264 (1339.0MB)
   OldSize                  = 176160768 (168.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 442499072 (422.0MB)
   used     = 370014664 (352.8734817504883MB)
   free     = 72484408 (69.12651824951172MB)
   83.61930847167969% used
From Space:
   capacity = 252182528 (240.5MB)
   used     = 5951360 (5.6756591796875MB)
   free     = 246231168 (234.8243408203125MB)
   2.3599414468555096% used
To Space:
   capacity = 275251200 (262.5MB)
   used     = 0 (0.0MB)
   free     = 275251200 (262.5MB)
   0.0% used
PS Old Generation
   capacity = 2233466880 (2130.0MB)
   used     = 898804560 (857.1668243408203MB)
   free     = 1334662320 (1272.8331756591797MB)
   40.24257391271457% used

PS Old Generation占用2130MB内存,使用率为40.24257391271457%

FullGC后

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4213178368 (4018.0MB)
   NewSize                  = 88080384 (84.0MB)
   MaxNewSize               = 1404043264 (1339.0MB)
   OldSize                  = 176160768 (168.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 436731904 (416.5MB)
   used     = 1463824 (1.3960113525390625MB)
   free     = 435268080 (415.10398864746094MB)
   0.335176795327506% used
From Space:
   capacity = 8388608 (8.0MB)
   used     = 0 (0.0MB)
   free     = 8388608 (8.0MB)
   0.0% used
To Space:
   capacity = 257949696 (246.0MB)
   used     = 0 (0.0MB)
   free     = 257949696 (246.0MB)
   0.0% used
PS Old Generation
   capacity = 1550319616 (1478.5MB)
   used     = 115867584 (110.49993896484375MB)
   free     = 1434452032 (1368.0000610351562MB)
   7.473786876215336% used

简要说明

参数 说明
MaxHeapSize 堆栈最大值,默认值按内存不超过192m时最大堆内存为物理内存的一半,否则为物理内存的四分一
PS Old Generation 老年代内存信息
1.capacity:总分配内存
2.used:已使用内存
3.free:空闲内存
根据上面得知FullGC后老年代实际使用内存为110.49993896484375MB
根据调优公式老年代大概取值为110x3MB~110x4MB,这里取512MB
年轻代Xmn的设置为老年代存活对象的1-1.5倍,取512MB
由于堆内存大小(XmxXms)等于年轻代+老年代,所以得出 Xms=Xmx= 1024MB

完整参数信息

配置tomcat

根据上面的计算结果配置tomcat,在catalina.sh下面一行jvm参数JAVA_OPTS="$JAVA_OPTS -server -Xms1g -Xmx1g -Xmn512m"

#!/bin/sh
JAVA_OPTS="$JAVA_OPTS -server -Xms1g -Xmx1g -Xmn512m"

GC检查

参数调整后需要日常检查jvm状态,在运行一周后,对GC进行检查

jstat -gc <pid>

得到GC信息如下:

S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
41984.0 43008.0 0.0 26922.1 437760.0 362342.5 524288.0 315844.9 106456.0 101570.6 11008.0 10235.4 752 16.584 50 10.742 27.325
参数 说明
S0C Survivor0空间的大小。单位KB。
S1C Survivor1空间的大小。单位KB。
S0U Survivor0已用空间的大小。单位KB。
S1U Survivor1已用空间的大小。单位KB。
EC Eden空间的大小。单位KB。
EU Eden已用空间的大小。单位KB。
OC 老年代空间的大小。单位KB。
OU 老年代已用空间的大小。单位KB。
MC 元数据空间的大小。单位KB。
MU 元数据已用空间的大小。单位KB。
CCSC 压缩Class(Compressed class space)committed的内存空间大小
CCSU 压缩Class(Compressed class space)committed的内存已用空间空间
YGC 年轻代GC总次数
YGCT 年轻代GC总耗时
FGC FullGC总次数
FGCT FullGC总耗时
GCT GC总耗时

YGC平均耗时: YGCT/YGC
16.584s/752=22ms
FGC平均耗时:FGCT/FGC
10.742s/50=214.8ms

频繁的GC和较长的耗时由于Stop The World问题,因此很容易导致服务超时,引发性能问题。

完整参数信息

参数 说明
Heap Configuration: 堆内存初始化配置
└─MinHeapFreeRatio 对应jvm启动参数-XX:MinHeapFree Ratio设置JVM堆最小空闲比率(default 40)
└─MaxHeapSize 堆栈最大值,默认值按内存不超过192m时最大堆内存为物理内存的一半,否则为物理内存的四分一
对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
└─NewSize 对应jvm启动参数-XX:NewSize=设置JVM堆的‘年轻代’的默认大小
└─MaxNewSize 对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘年轻代’的最大大小
└─OldSize 对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老年代’的大小
└─NewRatio 对应jvm启动参数-XX:NewRatio=:‘年轻代’和‘老年代’的大小比率
└─SurvivorRatio 对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
└─MetaspaceSize 对应jvm启动参数-XX:MetaspaceSize元空间初始大小
└─CompressedClassSpaceSize 对应jvm启动参数-XX:CompressedClassSpaceSize(Compressed Class Space 空间大小限制)
└─MaxMetaspaceSize 对应jvm启动参数-XX:MaxMetaspaceSize元空间最大大小
└─G1HeapRegionSize 对应jvm启动参数-XX:G1HeapRegionSize,G1垃圾回收器Region大小,若未指定则默认最多生成2048块,每块的大小需要为2的幂次方
Heap Usage: 堆内存使用情况
PS Young Generation
Eden Space: Eden区内存分布
└─capacity Eden区总容量
└─used Eden区已使用
└─free Eden区剩余容量
└─xxx% used Eden区使用比率
From Space: 其中一个Survivor区的内存分布
└─capacity 总容量
└─used 已使用
└─free 剩余容量
└─0.0% used 使用比率
To Space: 另一个Survivor区的内存分布
└─capacity 总容量
└─used 已使用
└─free 剩余容量
└─0.0% used 使用比率
PS Old Generation: 老年代内存信息
└─capacity 总容量
└─used 已使用
└─free 剩余容量
└─0.0% used 使用比率
0

评论区