如果程序挂死,有时使用jstack查看进程中线程信息时,需要添加上-F参数,此时如果有死锁信息,则可能不会打印出死锁堆栈信息,使用jdb则可以查看当前死锁线程的运行堆栈。
如下模拟一个简单的死锁程序
- package com.demo.bootdemo;
- import java.util.HashMap;
- import java.util.Map;
- import org.springframework.context.ApplicationListener;
- import org.springframework.context.event.ContextRefreshedEvent;
- import org.springframework.stereotype.Component;
- @Component
- public class MyListeners implements ApplicationListener<ContextRefreshedEvent> {
- private Map map = new HashMap<>();
- private String lock = "aa";
- @Override
- public void onApplicationEvent(ContextRefreshedEvent arg0) {
- Thread t = new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (map) {
- System.out.println(Thread.currentThread().getName() + ": 获得map锁");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- synchronized (lock) {
- System.out.println(Thread.currentThread().getName() + ": 获得lock锁");
- }
- }
- }
- }, "t-1");
- Thread t2 = new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (lock) {
- System.out.println(Thread.currentThread().getName() + ": 获得lock锁");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- synchronized (map) {
- System.out.println(Thread.currentThread().getName() + ": 获得map锁");
- }
- }
- }
- }, "t-2");
- t.start();
- t2.start();
- }
- }
获取pid
假设当前不能直接连接27709虚拟机,需要使用参数-F
可以看出造成死锁的线程未t-1和t-2
使用jdb连接jvm
- jdb -connect sun.jvm.hotspot.jdi.SAPIDAttachingConnector:pid=27709
执行threads命令获取所有线程列表
获取线程“t-1”堆栈信息,如下图,结合上述模拟死锁的代码,很容易就能看出来是哪里的问题
类似的,获取线程“t-2”的堆栈信息
通过以上步骤,基本上可以确定问题代码了。
本例也是匆忙中简单查看了下文档,没有详看,后续有时间在进行补充,jdb文档如下
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr011.html#BABDHAHJ
补充:java 性能监控 jstack 线程死锁 JConsole 和 BTrace 图形化工具
java 性能监控 工具
除了 javac java javap 之外, jdk 安装包还提供了很多其他工具
列出 bin 目录下的文件
- TomChens-MacBook-Pro:Commands tomchen$ ls
- appletviewer javadoc jmap keytool serialver
- apt javah jmc native2ascii servertool
- extcheck javap jps orbd tnameserv
- idlj javaws jrunscript pack200 unpack200
- jar jcmd jsadebugd policytool wsgen
- jarsigner jconsole jstack rmic wsimport
- java jdb jstat rmid xjc
- java_home jhat jstatd rmiregistry
- javac jinfo jvisualvm schemagen
jvisualvm
可以在线安装很多插件, 这是最新的非常强大的多合一故障处理工具
生成 Heap Dump, 可以在OQL Console 执行类似 sql 语句的 OQL
jvisualvm 的 BTrace 插件
生产环境服务无法停止的时候, 而日志里的信息无法满足我们需要时候, 可以通过这个打印调用堆栈 参数 返回值等
jconsole
也是一个图形化的监控工具
jps 虚拟机进程状况工具
类似于 ps 命令
- jps -l
- 582 HttpFind
- 431 RefreshBlog.jar
- 585 sun.tools.jps.Jps
jstat 虚拟机统计信息监控工具
- jstat -gcutil 431
- S0 S1 E O P YGC YGCT FGC FGCT GCT
- 0.00 57.17 12.43 24.74 42.31 13 0.044 0 0.000 0.044
从中可以看出 survivor(S0 S1) eden (E) young GC(YGC) 等参数
- jstat -class 434
- Loaded Bytes Unloaded Bytes Time
- 17095 36897.7 1899 2970.9 14.87
类加载时间为14.87
jstack java堆栈管理工具
可以查看线程死锁
- jstack 582
- ......
- ......
- Found one Java-level deadlock:
- =============================
- "Thread-199":
- waiting to lock monitor 0x00007facb3027608 (object 0x00000007e786b528, a java.lang.Integer),
- which is held by "Thread-3"
- "Thread-3":
- waiting to lock monitor 0x00007facb3026108 (object 0x00000007e786b518, a java.lang.Integer),
- which is held by "Thread-8"
- "Thread-8":
- waiting to lock monitor 0x00007facb3027608 (object 0x00000007e786b528, a java.lang.Integer),
- which is held by "Thread-3"
- Java stack information for the threads listed above:
- ===================================================
- "Thread-199":
- at HttpFind$SyncAdd.run(HttpFind.java:52)
- - waiting to lock <0x00000007e786b528> (a java.lang.Integer)
- at java.lang.Thread.run(Thread.java:722)
- "Thread-3":
- at HttpFind$SyncAdd.run(HttpFind.java:53)
- - waiting to lock <0x00000007e786b518> (a java.lang.Integer)
- - locked <0x00000007e786b528> (a java.lang.Integer)
- at java.lang.Thread.run(Thread.java:722)
- "Thread-8":
- at HttpFind$SyncAdd.run(HttpFind.java:53)
- - waiting to lock <0x00000007e786b528> (a java.lang.Integer)
- - locked <0x00000007e786b518> (a java.lang.Integer)
- at java.lang.Thread.run(Thread.java:722)
- Found 1 deadlock.
jhat 虚拟机堆转储快照分析工具
jinfo java 配置信息工具
jmap java 内存印象工具
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。
原文链接:https://www.cnblogs.com/qq931399960/p/11316684.html