快速定位Java应用卡顿的原因

发布时间 2024-01-02 14:10:53作者: 济南小老虎

快速定位Java应用卡顿的原因


背景

同事的环境说出现了一周的卡顿现象. 
元旦加班期间告诉我时已经是2024.1.1下午五点了.
当时没有来得及去查看. 
上班之后发现问题很简单. 不过为了能够指导一下后续的工作.还是在这里总结一下操作过程.

判断问题的整体思路

0. 同事告知出现卡顿. 
   询问卡顿的现象: 程序启动后, 运行一段时间后就卡顿. 无法缓解. 

1. 查看宿主机以及虚拟机的情况:
   判断是否是宿主机性能导致问题. 发现宿主机的CPU较高, 但是大部分CPU在这一台机器上面. 

2. 进入Linux系统.  top -Hp 进行观察
   发现java进程占用CPU忽高忽低, 基本确认是在fullGC. 怀疑产品有内存泄露. 

3. jstat -gcutil $pid 1000 1000
   查看GC次数, 发现基本上10秒左右一次FullGC.基本确认存在问题. 

4. jcmd $pid GC.heap_dump /root/20240102.dump
   转储dump文件, 并且使用mat进行分析

5. 查看leak suspect 以及进行查看堆栈信息. 按照使用的堆区大小进行排序
   定位到具体的内存占用较高的点. 发现是发送消息时因为获取了所有的消息体导致内存占用量大. 并且消息发送一分钟一次,较为频繁.

6. 反馈给业务开发, 调整消息发送时的个数限制,以及增加频率限制. 避免一次性进行所有消息的发送, 导致系统阻塞. 

关于jcmd命令的使用

jcmd 从jdk7 开始就是java自带的应用了
其实是java应用里面进行定位问题的最佳工具之一. 

需要建议, 如果程序使用哪个版本的java, 必须使用相同版本的 jcmd 等工具进行分析
不然那会出现加载失败等的问题. 

jcmd 的命令介绍

jcmd -l
与jps 一样 展示所有的 正在运行的java 进程.

jcmd $pid help 
查看jcmd的帮助列表, 需要说明. 不同版本的jcmd包含的命令不太一样
可以直接使用jcmd 0 help 进行查看.

[root@CentOS8 ~]# jcmd 0 help
2096872:
The following commands are available:
VM.native_memory
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

比较常用的其实有

jcmd 0 VM.flags
jcmd 0 VM.system_properties
jcmd 0 VM.command_line
jcmd 0 GC.heap_info
jcmd 0 GC.class_histogram
jcmd 0 Thread.print 
jcmd 0 GC.heap_dump /path/to/gcfile

除此之外 还有
jstat -gcutil pid 1000 1000 每秒钟展示一次gc信息.