问题:客户反馈应用异常、访问服务出现504问题。
现象:Nginx请求个别节点出现499错误码,应用节点无日志输出。
使用jstat工具查看Full GC情况,分析full gc次数是否频繁,确认应用本身是否有问题。
使用jmap查看当前应用进程使用内存,分析是否存在内存飙升等问题。
方法一:
# 第五列为虚拟内存占用情况,第六列为实际内存占用情况,默认单位kb。
ps -aux | grep MyApp.jar
# 实际内存以M为单位
ps -aux | grep MyApp.jar | awk '{sum=$6/1024} {print $0 " " $1 " " sum " MB"}'
方法二:
# 通过ps查找进程id
ps -ef | grep MyApp.jar
# 通过top -p命令查看内存占用
top -p <pid>
Java Heap Dump 是特定时刻 JVM 内存中所有对象的快照。它们对于解决内存泄漏问题和分析 Java 应用程序中的内存使用情况非常有用。
Java Heap Dump 通常以二进制格式的 hprof 文件存储。我们可以使用 jhat 或 JVisualVM 之类的工具打开和分析这些文件。同样,使用 MAT 工具分析是很常见的。
启动参数配置生成dump日志:
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/tmp/heapdump.hprof -jar MyApp.jar
临时生成dump日志:
如果没有配置dump日志,则不要直接停掉应用,先生成dump日志。
# 0.查看PID
ps -aux | grep MyApp.jar
jps
###################################
# 1.1生成dump日志
jmap -dump:format=b,file=/tmp/jmap_heapdump.hprof <pid>
# 1.2生成dump日志(live只保留存活的对象),如果运行时间长,防止heap过大
jmap -dump:live,format=b,file=/tmp/heapdump.hprof <pid>
###################################
# jcmd是java 8引入的集大成的诊断工具。
# 使用jcmd生成dump日志
jcmd <pid> GC.heap_dump /tmp/jcmd_heapdump.hprof
JProfiler
visualvm
官网:https://visualvm.github.io/
github:https://github.com/oracle/visualvm
启动参数配置生成gc日志:
java -Xloggc:gc.log -jar MyApp.jar
# 1.找到cpu最高的进程的id
top -c
# 查询java进程前五并进行排序
ps aux|grep java|grep -v grep|head -5|awk '{print $3,$1,$2}'|sort -rn
# 2.打印这个进程的所有线程的运行堆栈
jstack -l <pid> > /tmp/jstack.log
# 3.当前进程所有线程消耗情况
top -H -p <pid>
ps -mp <pid> -o THREAD,tid,time
# 4.找到CPU负载最高的线程, 把线程ID转换成16进制,(10进制转16进制,printf "%x\n" tid)
printf "%x\n" <tid>
# 5.搜索16进制显示的线程ID,定位到具体代码
vim jstack.log
# -A100是日志行数
# jstack |grep 16进制线程号 -A100
netstat -nap | grep <pid>
jmap:查看内存信息
# 查看新生代老年代
jmap -heap pid
# 生成dump文件
jmap -dump:live,format=b,file=/tmp/heapdump.hprof <pid>
Jstack:进程、线程、堆栈
# 打印这个进程的所有线程的运行堆栈
jstack -l <pid>
# 输出heap的直方图,包括类名,对象数量,对象占用大小
jmap -histo <pid>
# 输出堆内存设置和使用情况(JDK11使用jhsdb jmap --heap --pid pid)
jmap -heap <pid>
Jinfo:查看jvm的参数
Jinfo <pid>
Jstat:堆内存各部分的使用量,以及加载类的数量
# 输出gc信息,包括gc次数和时间,内存使用状况
jstat -gc <pid>
jstat -gcutil <pid>
Jcmd:从JDK 7开始提供,jcmd拥有jmap的大部分功能,官方推荐使用jcmd命令替代jmap命令。
# 列出所有的JVM进程
jcmd -l
# 针对指定的进程,列出支持的所有命令
jcmd <pid> help