Java-Jstack-生产问题的排查死锁/泄露/cpu负载

排查死锁

首先如果是本地开发环境可以通过JVisualVM查看是否有长时间休眠的线程

  • 注意:正式部署版本不会用JVisualVM,会留下漏洞

在这里插入图片描述

jdk自带的jstack排查死锁

  • 命令:jps 查看服务器上所有java服务进程
  • 命令:jstack PID 打印当前服务运行的所有线程快照,

也可以通过jstack PID > a.txx 将线程快照输出到文件中便于查看,文档的最下发会显示该进程中存在多少个死锁

jstack [PID] > [fileName].txt

在这里插入图片描述

  • 快照文件内直接搜deadlock如果有结果表示存在死锁, 有提示那行代码出现了死锁,以及为什么死锁的提示

快照中对死锁提示:
- 可以看到线程A,当前拥有的lock锁名为AA,需要获取名为BB的锁
- 线程B,拥有的lock锁名为BB,需要获取名为AA的锁
- 所以线程A和线程B就会产生死锁

最后根据提示死锁出现在代码的位置,自行去查看修改代码

jdk自带的jconsole排查死锁

  • [javaPath]\bin\jconsole.exe

说明:jconsole可以监视本地java进程和远程java进程,监视远程java进程需要配置用户名、口令

在这里插入图片描述
排查死锁 -> 点击“检测死锁”按钮

在这里插入图片描述

排查CPU爆满

  • 定位到哪一个程序CPU占用率高(定位进程PID), 使用top命名查看服务器cpu使用情况:
    在这里插入图片描述

  • 定位是那个JAVA程序

jps -l | grep 进程pid
或
jps 进程pid

这行命令的作用是通过jps -l打印进程pid对应的java程序是哪一个,至于grep只是为了过滤。

  • 定位到哪一个线程CPU占用率高 (定位线程TID)
ps -mp 进程pid -o THREAD,tid,time

通过此命令来获取CPU占用高的线程TID
在这里插入图片描述
通过%CPU和TIME,判断占用高的线程TID
需要将上图中的TID,转换成16进制(如:21111转为16进制=18a8),然后在下面的第四步(jstack 进程id > ps.txt)导出的文件中搜索,就可以定位到具体有问题的线程,类

-例如:TID=21111 那么将21111转为16进制就是0x18a8
  • 打印进程的线程快照
jstack [PID] > [fileName].txt

命令说明:输出该进程线程快照到txt文件中

在这里插入图片描述

内存溢出、泄漏

oom异常分为两种情况:

1.内存溢出:申请空间不足

2.内存泄漏:对象未被回收导致堆爆满,例如一直往一个Static的list塞数据,不用的数据未清除

  • 输出gc日志到指定文件 -Xloggc: (例如: -Xloggc:D:\logs\gc.log)

    • 生产环境会对输出的gc日志进行分块输出(防止单个文件过大):CSDN
  • 配置jvm参数:内存溢出后打印日志输出到.dump文件中

    • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.dump 来指定dump路径
  • 完整的启动jar命令:

    • jar - jar -XX指定gc日志输出目录 -xx内存溢出时候打印堆内存快照 -xx指定堆溢出快照日志输出目录
java -jar -Xloggc:/tmp/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.dump Demo-0.0.1-SNAPSHOT.jar

生成的.dump快照文件非常大 = 堆内存大小。

注意 jmap命令也可以打印堆快照,但是会暂停服务的运行(生产环境不允许用jmap取堆快照)

  • 打印堆内存状态: 命令:jstat -gcutil PID
    在这里插入图片描述
    SO、S1、Eden、O为老年代、M为元空间(方法区)、 CCS、YGC=新生代gc次数、YGCT=新生代gc耗时、FGC=老年代gc次数、FGCT=老年代gc耗时、GCT=所有gc一共耗时。

排查内存溢出

  1. 程序里有大对象

  2. 大对象被谁引用

通过jVisualVM打开.dump堆快照:

在这里插入图片描述
导入之后

visualvm概要页会提示:具体线程http-nio-8080-exec-1出现OutOfmEemoryError异常。

点击概要页最下方的"显示线程"按钮,显示线程快照,从中找到(搜索)http-nio-8080-exec-1线程,可以定位到内存溢出的具体类、代码行。

定位 - 内存泄漏

定位方法和内存溢出相同。

如果查找大对象 - 通过visualvm中的"类"查找大对象。

内存溢出实战

  1. 设置jvm参数,OutOfMemoryError时打印当前内存快照到指定文件中。
    在这里插入图片描述
  2. 不断往堆内存中添加数据,报OutOfMemoryError后会将当前内存快照输出到指定目录的heapdump.dump文件中
    在这里插入图片描述
  3. 打开jvisualvm.exe,点击文件->装入,选中heapdump.dump文件打开
    在这里插入图片描述
    在这里插入图片描述
    3.1. 通过“类”来查看到类的实例数量,36w多个实例…

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值