排查死锁
首先如果是本地开发环境可以通过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一共耗时。
排查内存溢出
-
程序里有大对象
-
大对象被谁引用
通过jVisualVM打开.dump堆快照:
导入之后
visualvm概要页会提示:具体线程http-nio-8080-exec-1出现OutOfmEemoryError异常。
点击概要页最下方的"显示线程"按钮,显示线程快照,从中找到(搜索)http-nio-8080-exec-1线程,可以定位到内存溢出的具体类、代码行。
定位 - 内存泄漏
定位方法和内存溢出相同。
如果查找大对象 - 通过visualvm中的"类"查找大对象。
内存溢出实战
- 设置jvm参数,OutOfMemoryError时打印当前内存快照到指定文件中。
- 不断往堆内存中添加数据,报OutOfMemoryError后会将当前内存快照输出到指定目录的heapdump.dump文件中
- 打开jvisualvm.exe,点击文件->装入,选中heapdump.dump文件打开
3.1. 通过“类”来查看到类的实例数量,36w多个实例…