JVM调优的核心思路(万变不离其宗)

154 阅读3分钟

1、预备知识

需要知道下面几个jvm参数和java命令

(1)jsp(PS:查看java进程号)

(2)jinfo -flags (PS:查看当前jvm参数,pid是java进程号)

参数太多了,大部分都可以见名思意,看不懂的百度参数含义即可~

(3)jstat -gc (PS:垃圾回收统计,这个是调优的核心命令比较常用)

命令的格式如下:

jstat -gc [间隔时间(毫秒)] [查询次数]

S0C:第一个幸存区的大小,单位KB

S1C:第二个幸存区的大小

S0U:第一个幸存区的使用大小

S1U:第二个幸存区的使用大小

EC:伊甸园区的大小

EU:伊甸园区的使用大小

OC:老年代大小

OU:老年代使用大小

MC:方法区大小(元空间)

MU:方法区使用大小

CCSC:压缩类空间大小

CCSU:压缩类空间使用大小

YGC:年轻代垃圾回收次数

YGCT:年轻代垃圾回收消耗时间,单位s

FGC:老年代垃圾回收次数

FGCT:老年代垃圾回收消耗时间,单位s

GCT:垃圾回收消耗总时间,单位s

2、核心思路

(1)优化思路

减少Full GC的次数,因为频繁的Full GC对JVM性能有影响,所以需要尽量让每次Young GC的存活对象小于Survivor区域的50%(原理看上面的“动态对象年龄判定”),让对象尽可能的留在年轻代,别让对象进入老年代。

(2)运行情况预估:

需要大概计算出“年轻代对象增长的速率”、“Young GC的频率和次数”、“执行Young GC后多少对象进入老年代”、“Full GC的频率和次数”。

1)年轻代对象增长的速率

执行命令 jstat -gc 10000 10 (每隔1秒执行1次命令,共执行10次),通过观察EU(eden区的使用)来估算每秒eden大概新增多少对象,这里的频率可以按照实际情况来指定。

2)Young GC的频率和次数

知道年轻代对象增长速率就能推根据Eden区的大小推算出Young GC大概多久触发一次,这里就可以找知道Young GC的频率和次数了。

3)执行Young GC后多少对象进入老年代

这个因为之前已经大概知道Young GC的频率,假设是每1分钟一次,那么可以执行命令 jstat -gc pid 100000 10 ,观察每次结果eden, survivor和老年代使用的变化情况,在每次gc后eden区使用一般会大幅减少,survivor和老年代都有可能增长,这些增长的对象就是每次 Young GC后存活的对象,同时还可以看出每次Young GC后进去老年代大概多少对象,从而可以推算出老年代对象增长速率

4)Full GC的频率和次数

知道了老年代的增长速率和老年代的大小,就可以推出Full GC的频率和次数了。

(3)优化的手段

优化主要从两方面入手 jvm参数和业务代码。

1)jvm参数

具体要看使用了哪个垃圾收集器(CMS、G1、ZGC...),可能需要调大年轻代的内存和缩小老年代内存等等。

2)业务代码

有可能是在某个高频调用的函数内new了个大对象

jmap -histo

这种情况可以通过jamp查看,查看class占的内存。

如果这个class很多地方被使用了,可以通过jvisualvm去定位代码(jvisualvm的使用说明,百度即可)

(4)案例

待补充......