jstack+jdb命令查看线程及死锁堆栈信息的实例

如果程序挂死,有时使用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 内存印象工具

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Java多线程之死锁的出现和解决方法

    什么是死锁? 死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不能正常运行.形象的说就是:一个宝藏需要两把钥匙来打开,同时间正好来了两个人,他们一人一把钥匙,但是双方都再等着对方能交出钥匙来打开宝藏,谁都没释放自己的那把钥匙.就这样这俩人一直僵持下去,直到开发人员发现这个局面. 导致死锁的根源在于不适当地运用"synchronized"关键词来管理线程对特定对象的访问."synchronized"关

  • java线程死锁代码示例

    死锁是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一. 事实上,计算机世界有很多事情需要多线程方式去解决,因为这样才能最大程度上利用资源,才能体现出计算的高效.但是,实际上来说,计算机系统中有很多一次只能由一个进程使用的资源的情况,例如打印机,同时只能有一个进程控制它.在多通道程序设计环境中,若干进程往往要共享这类资源,而且一个进程所需要的资源还很有可能不止一个.因此,就会

  • Java线程死锁实例及解决方法

    这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.死锁的定义 所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进 2.死锁产生的必要条件 互斥条件:线程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个线程所占有.此时若有线程请求该资源,则请求线程只能等待. 不剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程倾向夺

  • jstack+jdb命令查看线程及死锁堆栈信息的实例

    如果程序挂死,有时使用jstack查看进程中线程信息时,需要添加上-F参数,此时如果有死锁信息,则可能不会打印出死锁堆栈信息,使用jdb则可以查看当前死锁线程的运行堆栈. 如下模拟一个简单的死锁程序 package com.demo.bootdemo; import java.util.HashMap; import java.util.Map; import org.springframework.context.ApplicationListener; import org.springfr

  • dos下通过wmic命令查看硬盘和内存/CPU信息(windows自带命令查看硬件信息)

    如何在windows系统自带命令查看硬件信息,怎样dos命令查看硬盘和内存/CPU信息?最直接的是:开始→运行→CMD打开命令提示符,在该窗口下输入systeminfo执行,即可看到几乎所有想知道的系统信息,甚至包括机器上已安装的网卡及其IP. 问题描述: 如何从系统中 查看主板上内存条的数量.最佳答案: 在cmd命令下 输入:wmic memorychip list brief 或者 wmic MEMPHYSICAL list brief 就会看到内存条的数量 rem 查看cpu wmic c

  • java自带的工具Jstack截取进程中的堆栈信息

    在Java软件的使用过程中,有时会莫名的出现奇怪的问题.而这些问题常常无法使用日志信息定位,这时我们就需要通过查看进程内部线程的堆栈调用关系来分析问题出在哪里. 举个例子,当我们在做某个操作时,莫名的会弹出多个警告框,其中有些信息是正常的,有些则不是.对于这些错误的警告信息,我们该如何定位是哪个位置的代码出现了错误弹出的框呢? 我们就需要在弹框以后,去查看软件的各个线程,去查找究竟是哪个线程导致了该问题.可是有时因为环境.时间等问题,我们根本不能拿着IDE去调试, 只能通过工具软件拍下内存快照,

  • java线程之死锁

    目录 一.什么是死锁 二.死锁产生的原因 三.死锁演示 1.synchronized 2.lock 四.如何查看死锁 1.使用jps命令找到运行程序的pid 2.jstack查看栈信息 一.什么是死锁 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程. 二.死锁产生的原因 1.互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某

  • 如何定位java程序中占用cpu最高的线程堆栈信息

    找出占用cpu最高的线程堆栈信息 在java编码中,有时会因为粗心导致cpu占用较高的情况,为了避免影响程序的正常运行,需要找到问题并解决.这里模拟一个cpu占用较高的场景,并尝试定位到代码行. 示例代码如下: public class Math { public static final int initData = 666; public static User user = new User(); public int compute() { //一个方法对应一块栈帧内存区域 int a

  • Android adb logcat 命令查看日志详细介绍

    Android 开发的程序员开发程序的时候,一定为log而苦恼过吧.Eclipse老是Log找不到,是不是很让人不爽,虽然Android Studio的Logcat功能很不错,但也没有在命令行terminal中打印出来更方便. 使用 logcat 命令 查看和跟踪系统日志缓冲区的命令logcat的一般用法是: [adb] logcat [<option>] ... [<filter-spec>] ... 下文介绍过滤器和命令选项,详细内容可参见Listing of logcat C

  • Linux du命令查看文件夹大小并按降序排列

    1. df -lh 2. du -s /usr/* | sort -rn 这是按字节排序 3. du -sh /usr/* | sort -rn 这是按兆(M)来排序 4.选出排在前面的10个 du -s /usr/* | sort -rn | head 5.选出排在后面的10个 du -s /usr/* | sort -rn | tail du -h –-max-depth=0 user du -sh –-max-depth=2 | more 总结du常用命令 du -h --max-dept

  • 使用Curl命令查看请求响应时间方法

    curl命令查看请求响应时间 # curl -o /dev/null -s -w %{time_namelookup}::%{time_connect}::%{time_starttransfer}::%{time_total}::%{speed_download}"\n" http://www.36nu.com 0.014::0.015::0.018::0.019::1516256.00 -o:把curl 返回的html.js 写到垃圾回收站[ /dev/null] -s:去掉所有状

  • Linux通过sar命令查看网卡流量

    sar(System Activity Reporter系统活动情况报告)是目前 Linux 上最为全面的系统性能分析工具之一,可以从多方面对系统的活动进行报告,包括:文件的读写情况.系统调用的使用情况.磁盘I/O.CPU效率.内存使用状况.进程活动及IPC有关的活动等. sar命令参数很多,有时间man一下. -n参数很有用,他有6个不同的开关:DEV | EDEV | NFS | NFSD | SOCK | ALL .DEV显示网络接口信息,EDEV显示关于网络错误的统计数据,NFS统计活动

  • linux使用lsof命令查看文件打开情况

    前言 我们都知道,在linux下,"一切皆文件",因此有时候查看文件的打开情况,就显得格外重要,而这里有一个命令能够在这件事上很好的帮助我们-它就是lsof. linux下有哪些文件 在介绍lsof命令之前,先简单说一下,linux主要有哪些文件: 普通文件 目录 符号链接 面向块的设备文件 面向字符的设备文件 管道和命名管道 套接字 以上各类文件类型不多做详细介绍. lsof命令实用用法介绍 lsof,是list open files的简称.它的参数很多,但是我们这里只介绍一些实用的

随机推荐