JVM实践(三)JVM调优案例
大部分的JVM调优,目的是降低GC次数,减少GC时间(STW耗时占大部分)。
从原因分析上
FULL GC频率高。正常10天半个月可能FULL GC一次,如果一天两三次就不正常了。
可能的原因:
(1)内存泄漏,属于代码问题。
首先分析大对象,找到它,修复它,可能是代码上的缺陷,又或者是程序设计上漏洞。
(2)元空间(metaspace,Java8后才有,以前是“永久代”)超了。项目代码量很大,类的基本信息(或者说静态数据)撑爆了元空间,触发了GC。
java -XX:+PrintFlagsInitial|grep MetaspaceSize 查看元空间初始值
修改默认值16m--->32m
-XX:MetaspaceSize=32m
具体案例分析
其实到现在,是不是觉得还是手足无措,第一次吃饭,不知道怎么吃,不知道饭是怎么到肚子里的。不知道用碗盛饭,不知道用筷子夹菜,不知道用勺子舀汤。想知道怎么做吗? 别问我,我也不知道,睡觉去。
案例1:我可以想象一下,假设你系统运行很慢——堆内存不足
首先,登录linux服务器,输入命令jps,找到java的进程号。
然后,看一下性能情况,也就是GC情况,输入命令:jstat -gc -t [进程号] 1s 5
1).有可能你看到了GC次数多次。
那么,你可以看下堆内存分配情况:jmap -heap [进程号]
如果最大堆内存很小,就调大一下比如:512m-->4096m。
案例2:系统启动很慢——元空间不足
同样,jstat分析一下FULL GC情况,如果发现,唉,在启动的时候居然还FULL GC了一两次,那一般就是你的元空间不足啦。
-XX:MetaspaceSize=32m 16m-->32m
案例3:同样系统运行慢——代码内存泄漏
开头已经说过了,找到可能出现在老年代的大对象,这种啃老族应该找出来消灭它。那怎么操作呢?
首先,必须的两步肯定是 看进程号,看jstat。确认FULL GC次数多,然后再用jmap查看堆内存分配,那这种情况肯定是老年代存活了很多大对象了。看下图中那个used使用量,如果大于0肯定是存活着对象了。
接着,分析堆内存。有两种方式可以跟踪:
1.实时:jmap -dump:format=b,file=e:\a\heap.hprof [进程号] 实时查看jvm内存信息。
2.溢出跟踪:jvm启动参数中添加 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=e:\a\java.hprof
此方法可以在内存溢出的时候dump出.hprof文件。可以下载到windows本地,然后在JDK的bin目录下,文件名就叫jvisualvm.exe点击运行,选择hprof文件,就可以分析了。
最后,分析到原因了,就改bug吧。