目的
- 更好的回收频率和更短的回收耗时
- 更好的内存利用率
调优策略
两个基本原则:
- 将转移到老年代的对象数量降到最少。
- 减少Full GC的执行时间。目标是Minor GC时间在100ms以内,Full GC时间在1s以内。
主要调优参数:
- 设定堆内存大小,这是最基本的。
- -Xms:启动JVM时的堆内存空间。
- -Xmx:堆内存最大限制。
- 一般将Xms与Xmx设置成相同大小避免扩容时消耗性能
- 设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代。
- -XX:NewRatio:新生代和老年代的占比。
- -XX:NewSize:新生代空间。
- -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比。
- -XX:MaxTenuringThreshold:对象进入老年代的年龄阈值。
- 设定垃圾回收器
年轻代:-XX:+UseParNewGC。
老年代:-XX:+UseConcMarkSweepGC。
调优设置
依据Java Performance推荐公式
- Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
- 永生代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍(JDK8从已经将永生代迁到元数据区)。
- 年轻代Xmn的设置为老年代存活对象的1-1.5倍。
- 老年代的内存大小设置为老年代存活对象的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 |
|
由于堆内存大小(Xmx 和 Xms )等于年轻代+老年代,所以得出 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 | 使用比率 |
评论区