JVM调优工具很多,底层还是这些指令在运行,可能不同的工具封装了这些指令。
1.jmap
jmap用来查看内存的信息。
jmap -histo pid > ./log.txt
jmap -heap pid
jmap -dump:format=b,file=eureka.hprof pid
2.jstack
查看死锁的情况
查看堆中的信息
查看jvm进程中cpu飙升的原因,可以定位到代码的行数
jstack -pid
top -p
jstack 19663|grep -A 10 4cd0
3.jinfo
查看jvm、java的参数,系统的参数
jinfo -flags pid
4.jstat
用的最多
查看垃圾回收的详细信息
jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
jstat -gc pid time count
5.jvisualvm
jdk自带的工具,视图化,查看死锁,对象实例,GC堆内存的转化情形
实战分析
首先,我们对我们自己开发的系统有一定的了解,知道配置的jvm参数是什么样子的。举个例子
-Xms1536M -Xmx1536M -Xmn512M -Xss256K -XX:SurvivorRatio=6 -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly
第一步:
使用jstat -gc pid time count,查看堆内存的使用情况。是YoungGC过多,还是FullGC过多。GC的次数怎么样,耗时时间怎么样???
分析问题:可能是老年代动态年龄机制,导致FullGC这么频繁,这样的话,第二步:
需要调整年轻代与老年代的比例试试,调整如下:
-Xms1536M -Xmx1536M -Xmn1024M -Xss256K -XX:SurvivorRatio=6 -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSInitiatingOccupancyOnly
第三步:
继续使用jstat -gc pid timecount,查看堆内存中的YoungGC,FullGC情况。如果还没达到预想的结果。GC还是很频繁。甚至FullGC比YoungGC还要多,这可能是老年代担保机制造成的。可能有很多大对象产生
第四步:
使用jmap -histo pid,查看是否有对象实例数很多,可以大致定位到这些对象。
第五步:
使用jvisualvm,查看到具体的对象实例,以及这些大对象的方法。进而找到对应的代码,进行修改。理解,在理解的基础上,分析问题。不要怕尝试,jvm调优是一个过程,需要慢慢尝试,慢慢优化。
我们写代码的时候,也是需要考虑到,一下子创建的对象数量会不会太大了,造成GC。