jvm问题排查
常用工具
命令查询资源信息
top:显示系统整体资源使用情况
vmstat:监控内存和 CPU
iostat:监控 IO 使用
netstat:监控网络使用
查看java进程
jps
查看运行时信息
jinfo pid
gc工具
jstat: 查看jvm内存信息
GCViewer — 离线分析GC日志
gceasy: https://gceasy.io/
gceasy 使用:https://blog.csdn.net/weixin_42030357/article/details/122707538
堆栈分析工具
jstack: 查看堆栈信息、锁等待信息、导出堆栈信息
fastThread: https://www.fastthread.io/
MAT — 分析堆转储文件
fastThread使用:https://www.6hu.cc/archives/115077.html
堆信息分析
jmap: 生成堆转储快照
jvisualvm: java自带的分析工具
heap hero: https://heaphero.io/
jhat:堆转储快照分析
性能优化工具
XXFOX
Arthas(阿尔萨斯)
相关参数
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-Xss:规定每个线程虚拟机栈大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为 3 表示年轻代和年老代比值为 1:3,年轻代占整个年轻代年老代和的 1/4
-XX:SurvivorRatio=n:年轻代中 Eden 区与两个 Survivor 区的比值。注意 Survivor 区有两个。如 3 表示 Eden:3 Survivor:2,一个 Survivor 区占整个年轻代的 1/5
-XX:MaxPermSize=n:设置持久代大小
-XX:MaxTenuringThreshold=n:设置经过多少次GC进入老年代
-XX:PretenureSizeThreshold=n :设置多大对象直接进入老年代,单位:byte
-XX:+HeapDumpOnOutOfMemoryError:OOM异常出现之后自动生成dump文件
-XX:HeapDumpPath=path 设置dump文件路径java -XX:+PrintCommandLineFlags -version:查看虚拟机配置
收集器设置:
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的 CPU 数。并行收集线程数
-XX:MaxGCPauseMillis=n:设置并行收集最大的暂停时间(如果到这个时间了,垃圾回收器依然没有回收完,也会停止回收)
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为:1/(1+n)
-XX:+CMSIncrementalMode:设置为增量模式。适用于单 CPU 情况
-XX:ParallelGCThreads=n:设置并发收集器年轻代手机方式为并行收集时,使用的 CPU 数。并行收集线程数
打印 GC 回收的过程日志信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
问题分析
问题排查一般关注四个指标
吞吐量
响应时间
报错信息
资源使用情况
cpu飚高如何排查
1. 启动:java -jar 2_cpu-0.0.1-SNAPSHOT.jar 8 > log.file 2>&1 &
2. 一般来说,应用服务器通常只部署了java应用,可以top一下先确认是否是java应用导致的:命令:top
3. 如果是,查看java进程ID,命令:jps -l
4. 找出该进程内最好非CPU的线程,命令:top -Hp <pid>
5. 将线程ID转化为16进制,命令:printf "%x\n" 线程ID
6. 导出java堆栈信息,根据上一步的线程ID查找结果:命令:jstack <pid> >stack.txt |grep 2ed7 stack.txt -A 20
7. 可以文件中直接搜16进制,80%情况可以直接定位到方法的信息或者将stack.txt导入fastThread进行分析一般查看线程数、锁等待、cpu线程、堆栈调用图
内存飚高如何排查
1. 先观察垃圾回收的情况:jstat -gcutil <pid> 1000(打印内存情况,一秒一次)jstat -gc <pid> 1000查看gc日志或者导入GC分析工具中
2. 如果每次 GC 次数频繁,而且每次回收的内存空间也正常,那说明是因为对象创建速度快导致内存一直占用很高
3. 如果每次回收的内存非常少,那么很可能是因为内存泄露导致内存一直无法被回收
4. 导出堆内存快照:jmap -dump:file=heap.dump <pid>
5. 导入工具中查看:jvisualvm 或者 heap hero,按照大对象倒序排列,一般就可以定位问题
Full GC问题排查
- 查看参数配置以及目前内存使用情况,是否是参数设置的问题,可能是内存参数设置的不合理,或者添加了一些其他参数导致的
- 分析堆内存快照,查看是否是因为内存泄漏导致的
- 查看cpu使用率,定位到线程中cpu使用率高的位置
- 是否手动调用了System.gc()
接口响应延迟排查
- 查看该接口具体调用耗时,可以使用链路追踪工具
- 那么可能有以下情况导致:
网络超时
调用了第三方接口或者其他服务
锁的等待
资源不够:线程资源、连接资源。。。
数据库sql执行时间长
缓存不能命中 - 检查jvm监控信息:gc回收频率,gc回收大小,各个区使用情况,大对象等
- 检查cpu、内存是否正常
- 检查应用qps是否负载过高