JVM排查问题常用命令工具和图形化工具

命令工具

jps检索进程

jps -l 输出主类的全名,如果进程执行的是Jar包则输出Jar路径
jps -v 输出虚拟机进程启动时JVM参数

jstat分代信息运行状态信息

监视虚拟机各种运行状态信息的命令行工具

jstat -gc pid [刷新毫秒] [打印条数]

在这里插入图片描述

 S0C:第一个幸存区的大小
 S1C:第二个幸存区的大小
 S0U:第一个幸存区的使用大小
 S1U:第二个幸存区的使用大小
 EC:伊甸园区的大小
 EU:伊甸园区的使用大小
 OC:老年代大小
 OU:老年代使用大小
 MC:方法区大小
 MU:方法区使用大小
 CCSC:压缩类空间大小
 CCSU:压缩类空间使用大小
 YGC:年轻代垃圾回收次数
 YGCT:年轻代垃圾回收消耗时间
 FGC:老年代垃圾回收次数
 FGCT:老年代垃圾回收消耗时间
 GCT:垃圾回收消耗总时间

jinfo实时地查看和调整虚拟机各项参数

jinfo pid
jinfo -flag MetaspaceSize <进程号>查看元空间大小

jmap生成堆转储快照

查看类的数量和所占大小,输出前30行
jmap -histo pid | head -30   或者|more分页查看
查看堆内存情况
jmap -heap pid

在这里插入图片描述

生成堆内存快照到指定目录
jmap -dump:format=b,file=/home/path/yyyyMMdd.hprof pid
通常在启动java程序的时候设置启动参数,发生OOM了自动dump
-XX:+HeapDumpOnOutOfMemoryError
指定输出目录
-XX:HeapDumpPath=/home/xx/dump

jhat分析jmap生成的堆转储快照(耗性能,用的少)

jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看
localhost:7000

jhat /xx/xx.hprof

jstack生成虚拟机当前时刻的线程快照(可检查线程死锁)

可以结合|more分页

jstack -l pid

线程死锁,可以看到具体类方法行数发生的死锁
在这里插入图片描述
并打印各个线程调用方法信息

日志解析

parallelScavenge+parallelOld日志解析

启动参数:

XX:+PrintGCDetails

日志:

[GC (Allocation Failure) [PSYoungGen: 65536K->4048K(76288K)] 65536K->4056K(251392K), 0.0234656 secs] [Times: user=0.09 sys=0.03, real=0.03 secs]
[GC (Allocation Failure) [PSYoungGen: 69584K->5248K(141824K)] 69592K->5264K(316928K), 0.0243941 secs] [Times: user=0.11 sys=0.03, real=0.03 secs] 
[GC (GCLocker Initiated GC) [PSYoungGen: 41701K->5456K(141824K)] 41717K->5472K(316928K), 0.0210557 secs] [Times: user=0.11 sys=0.02, real=0.02 secs] 
[GC (Metadata GC Threshold) [PSYoungGen: 14037K->5456K(272896K)] 14053K->5480K(448000K), 0.0204318 secs] [Times: user=0.13 sys=0.03, real=0.02 secs] 
[Full GC (Metadata GC Threshold) [PSYoungGen: 5456K->0K(272896K)] [ParOldGen: 24K->5262K(75776K)] 5480K->5262K(348672K), [Metaspace: 20667K->20667K(1069056K)], 0.0186367 secs] [Times: user=0.08 sys=0.00, real=0.02 secs]  

第一行日志:

GC (Allocation Failure)YoungGen内存分配失败触发GC

[PSYoungGen: 65536K->4048K(76288K)]
65536K=年轻代收集前占用的大小
4048K=收集后占用的大小
76288K=年轻代总共大小
 
65536K->4056K(251392K), 0.0234656 secs]
65536K=垃圾收集之前Java堆占用的大小
4056K=垃圾收集之后Java堆占用的大小
251392K=总堆大小1509376K
0.0234656 secs=垃圾收集过程所消耗的时间

[Times: user=0.09 sys=0.03, real=0.03 secs]
user=0.09=GC用户耗时(用户态)
sys=0.03=GC系统耗时(内核态)
real=0.03=GC实际耗时

第二行日志:

可以看出年轻代和,总的java堆内存总大小更大了,执行过扩容
扩容也是需要耗时间,可以在启动时指定起始大小减少频繁扩容

第三行日志:

GC (GCLocker Initiated GC)
使用本地方法JNI函数访问JVM中的字符串或数组数据(代码在临界区执行),必须保证原始数据不被修改,
防止其它线程的操作、或发生GC回收改字符串对象。利用GC_locker加锁,保证临界区代码的正确执行。
有线程进入了临界区,导致触发的YGC被丢弃。当线程执行完临界区的代码之后,执ReleaseStringCritical方法,
离开临界区,这个时候发现触发过gc,这个时候再触发gc

第四行日志:

GC (Metadata GC Threshold) 
元数据(方法区)空间不足触发GC

第五行日志:

Full GC (Metadata GC Threshold)
元数据(方法区)空间不足触发的Full GC
Class.forName动态动态加载类信息,实际上是在占用元数据区的空间,并发较大加载过多动态类信息可能导致元空间outOfMemoryError MetaSpace溢出
Class.forName慎用


[ParOldGen: 24K->5262K(75776K)]
老年代收集信息

[Metaspace: 20667K->20667K(1069056K)]
方法区收集信息
其他信息都是上面解析一样的格式方式解读即可

G1日志解析

可视化工具

jconsole

jvisualvm

jvisualvm比jconsole更强大,一般生产上不直接用图像工具

专业工具
arthas

排查流程

top查看占用较大资源进程
top -Hp pid 找到占用较大的线程编号 结合 jstack pid查看对应的线程
jstack查看的可能是 gc线程 或者 业务线程

如果是gc -> 一定是频繁gc导致线程飙高 -> 读gc日志

如果是业务 -> 查看对应线程调用的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可——叹——落叶飘零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值