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)案例
待补充......