定位 - 死锁
首先如果是本地开发环境可以通过JVisualVM查看是否有长时间休眠的线程。
注意:正式部署版本不会用JVisualVM,否则会留下漏洞。
一、jdk自带的jstack排查死锁
需要以下几步:
1. 命令:jps 查看服务器上所有java服务进程。
2. 命令:jstack PID 打印当前服务运行的所有线程快照,
也可以通过jstack PID > a.txx 例如:将线程快照输出到文件中便于查看,文档的最下发会显示该进程中存在多少个死锁。
3. 快照文件内直接搜deadlock如果有结果表示存在死锁
有提示那行代码出现了死锁,以及为什么死锁的提示。
快照中对死锁提示:
- 可以看到线程A,当前拥有的lock锁名为AA,需要获取名为BB的锁;
- 线程B,拥有的lock锁名为BB,需要获取名为AA的锁;
- 所以线程A和线程B就会产生死锁。
最后根据提示死锁出现在代码的位置,自行去查看修改代码。
二、jdk自带的jconsole排查死锁
\jdk\jdk8\bin\jconsole.exe
说明:jconsole可以监视本地java进程和远程java进程,
监视远程java进程需要配置用户名、口令。
排查死锁 -》点击“检测死锁”按钮
定位 - CPU爆满
1. 定位到哪一个程序CPU占用率高(定位进程PID)
使用top命名查看服务器cpu使用情况:
2. 定位是那个JAVA程序
-
jps -l | grep 进程pid
-
jps -v | grep 进程pid
-
jps 进程pid
这行命令的作用是通过jps -l
打印进程pid
对应的java程序是哪一个,至于grep只是为了过滤。
3. 定位到哪一个线程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
4. 打印进程的线程快照
jstack 进程pid > t.txt
命令说明:输出该进程线程快照到t.txt文件中。
内存溢出、泄漏
oom异常分为两种情况:
1.内存溢出:存在未被回收的大对象。
2.内存泄漏:新生代和老年代中的对象未被回收导致堆爆满。
1. 输出gc日志到指定文件 -Xloggc:
(例如: -Xloggc:D:\logs\gc.log)
生产环境会对输出的gc日志进行分块输出(防止单个文件过大):https://mp.youkuaiyun.com/console/editor/html/106739504
2. 配置jvm参数:内存溢出后打印日志输出到.dump文件中
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.dump 来指定dump路径
3. 完整的启动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取堆快照)。
4. 打印堆内存状态: 命令:jstat -gcutil PID
SO、S1、Eden、O为老年代、M为元空间(方法区)、 CCS、YGC=新生代gc次数、YGCT=新生代gc耗时、FGC=老年代gc次数、FGCT=老年代gc耗时、GCT=所有gc一共耗时。
定位 - 内存溢出
1. 程序里有大对象。
2. 大对象被谁引用。
通过jVisualVM打开.dump堆快照:
2. 导入之后
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多个实例...