JVM工具
jmap
- jmap -histo <pid> > ./log.txt : 打印JVM堆栈内存信息,实例个数以及占用内存大小
- jmap -heap <pid> : 实时查看JVM堆信息
- jmap -dump: format-b,file=log.hprof <pid>: 导出整个堆的快照信息
-
可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)
- -XX:+HeapDumpOnOutOfMemoryError
- -XX:HeapDumpPath=./<内存溢出日志的存放路径>
jvisualvm
- 本地自带的JVM图形化界面监控工具(底层就是通过JVM指令,以图形的形式显示),可远程监控,不过很少用,推荐使用Arthas
jinfo
- jinfo -flags <pid> : 打印JVM参数信息
jstack
-
问题: 如果CPU飙升或者死锁,该如何定位
- top -p <pid> : 显示进程的内存情况
- 按H: 获取进程中所有线程的内存情况
- jstack <pid> | grep -A 10(行数) <线程pid> : 线程pid是16进制,所以要把线程pid转成16进制
- 注意: 线程pid如果转成16进制会带有大写,需要转成小写,否则查不到
jstat
- jstat -gc <pid> 100(ms) 10(行数) <线程pid> : 查看堆内存各部分的使用情况,以及加载类的数量
- 当通过jmap和jstack命令无法分析出问题时,这时候jstat就非常方便,因为该命令可以将堆内存中所有区域(年轻代、老年代、方法区)的使用情况打印出来,通过JVM调优策略来分析具体情况
JVM运行情况预估
使用jstat命令打印的结果可以分析以下几点
-
年轻代对象增长的速率
- 可通过jstat -gc <pid> <time> <line>来实时监控Eden、Survivor区的使用情况,时间可以设置长一点,一般系统都会有高峰期和非高峰期,所以最好在不同的时间点分别评估对象的增长速率
-
YoungGC的触发频率和每次耗时
- 平均耗时公式: YGCT / YGC,可得出因为YoungGC的执行而卡顿的时间
-
每次YongGC后有多少对象存活和进入老年代
- 观察每次Eden、Survivor、老年代使用情况,如果每次GC后Eden区越来越少,就表示存活对象可能被移动到Survivor区和老年代,这些增长的对象都是YongGC后存活下来的对象,可以看出每次YoungGC后进入老年代的大概有多少对象,进而推算出老年代的增长速率
-
FullGC的触发频率和每次耗时
- 平均耗时公式: FGCT / FGC,可得出老年代触发的频率
根据以上几点分析得出结果,基本能找到问题,但是有些分析不出来的问题,可能是某些代码造成性能问题
- 注意: 频繁FullGC会导致系统卡顿,如果是因为老年代空间分配担保机制而触发的FullGC的情况,可能因为是老年代空间比较小
- 在写处理大数据量的业务代码的时候,先要评估系统的性能是否能支撑你的业务逻辑,如果系统性能一般,尽量不要一次性处理大数据集进行业务处理(比如一次性查几千条记录,会产生几千个对象),可以分批处理
内存泄露
使用的对象(如HashMap)长时间没有及时处理,导致数据越存越多,一直占用老年代空间,时间久了就会触发FullGC,甚至因为老年代达到阈值,回收不完而导致OOM,这就是一种内存泄露
JVM工具使用流程
详细链接: www.processon.com/view/link/6…

- 如果遇到内存飙升,可以通过jmap找出创建最多的对象实例,也就是对象实例占用的内存大小
- 如果是CPU飙升,可以通过jps查看所有Java进程,再通过top查看每个进程占用内存情况,并且定位到问题比较大的进程,然后通过jstack找到对应线程ID下的堆栈信息看看能不能定位问题,如果不能就通过jstat去查看堆内存的使用情况,看看YongGC是否频繁,如果频繁就适当调整动态年龄参数,如果不频繁看看FullGC是否频繁,如果频繁分析下是不是因为老年代空间太小的原因
作者:枫度柚子
链接:https://juejin.cn/post/7100638569261170702
来源:稀土掘金
网友评论