jstack 使用

dump 文件里,值得关注的线程状态有:

  1. 死锁,Deadlock(重点关注) 
  2. 执行中,Runnable
  3. 等待资源,Waiting on condition(重点关注)
  4. 等待获取监视器,Waiting on monitor entry(重点关注)
  5. 暂停,Suspended
  6. 对象等待中,Object.wait() 或 TIMED_WAITING
  7. 阻塞,Blocked(重点关注)  
  8. 停止,Parked

Runnable:不解释

Wait on condition:该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。最常见的情况是线程在等待网络的读写。如果网络数据没准备好,线程就等待在那里。另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。

Waiting for monitor entry 和 in Object.wait():这两种情况在多线程的情况下经常出现。Java是通过Monitor来实现线程互斥和协作(有些把Monitor直译成锁,我认为不妥,不是还有Lock嘛)。具体Monitor的深入理解见 http://www.cnblogs.com/tomsheep/archive/2010/06/09/1754419.html

但是可以理解成Monitor是一个对象或者class所拥有的锁,每个对象和class有且仅有一个。见下图.

每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。

在 “ Entry Set”里面的线程都等待拿到Monitor,拿到了线程就成为了Runnable线程,否则就会一直处于处于 “waiting for monitor entry”。一段代码作为例子

public class MyThread implements Runnable{    

     public void run() {
         synchronized(this) {
              for (int i = 0; i < 1; i--) {
                   System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
              }
         }
    }
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
         Thread ta = new Thread(t1, "A");
         Thread tb = new Thread(t1, "B");
         ta.start();
         tb.start();
    }   

}  

大家一看就知道,B线程肯定是“千年老二“,永远拿不到Monitor了。

对应的stack:

"B" prio=10 tid=0x0969a000 nid=0x11d6 waiting for monitor entry [0x8bb22000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.marshal.MyThread.run(MyThread.java:7)
    - waiting to lock <0x94757078> (a org.marshal.MyThread)
    at java.lang.Thread.run(Thread.java:636)  

"A" prio=10 tid=0x09698800 nid=0x11d5 runnable [0x8bb73000]
   java.lang.Thread.State: RUNNABLE
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(FileOutputStream.java:297)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
    - locked <0x947571b0> (a java.io.BufferedOutputStream)
    at java.io.PrintStream.write(PrintStream.java:449)
    - locked <0x94757190> (a java.io.PrintStream)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:220)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:290)
    at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:103)
    - locked <0x947572a0> (a java.io.OutputStreamWriter)
    at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
    at java.io.PrintStream.write(PrintStream.java:494)
    - locked <0x94757190> (a java.io.PrintStream)
    at java.io.PrintStream.print(PrintStream.java:636)
    at java.io.PrintStream.println(PrintStream.java:773)
    - locked <0x94757190> (a java.io.PrintStream)
    at org.marshal.MyThread.run(MyThread.java:8)
    - locked <0x94757078> (a org.marshal.MyThread)
    at java.lang.Thread.run(Thread.java:636)  

<0x94757078> 就是两个线程争夺的Monitor

在 “Wait Set”里面的线程都如饥似渴地等待拿到Monitor。他们是怎么进入到“Wait Set”的呢?当一个线程拿到了Monitor,但是在其他资源没有到位的情况下,调用同步锁对象(一般是synchronized()内的对象)的 wait() 方法,放弃了 Monitor,它就进入到了 “Wait Set”队列。只有当其他线程通过notify() 或者 notifyAll(),释放了同步锁后,这个线程才会有机会重新去竞争Monitor。在stack中,它表现的状态是in Object.wait()。修改上面的代码public class WaitThread implements Runnable{

public void run() {
      synchronized(this) {
        try {
        this.wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      }
 }
 public static void main(String[] args) {
   WaitThread t1 = new WaitThread();
      Thread ta = new Thread(t1, "A");
      Thread tb = new Thread(t1, "B");
      ta.start();
      tb.start();
 }   

对应的stack:

"B" prio=10 tid=0x08173000 nid=0x1304 in Object.wait() [0x8baf2000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0xa9cb50e0> (a org.marshal.WaitThread)
    at java.lang.Object.wait(Object.java:502)
    at org.marshal.WaitThread.run(WaitThread.java:8)
    - locked <0xa9cb50e0> (a org.marshal.WaitThread)
    at java.lang.Thread.run(Thread.java:636)  

"A" prio=10 tid=0x08171c00 nid=0x1303 in Object.wait() [0x8bb43000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0xa9cb50e0> (a org.marshal.WaitThread)
    at java.lang.Object.wait(Object.java:502)
    at org.marshal.WaitThread.run(WaitThread.java:8)
    - locked <0xa9cb50e0> (a org.marshal.WaitThread)
    at java.lang.Thread.run(Thread.java:636)  

A和B线程都进入了”wait set“。B线程也拿到过这个Monitor,因为A线程释放过了,这也验证上面的话,他们都在等待得而复失的<0xa9cb50e0>

转自  http://go-on.iteye.com/blog/1673894

时间: 2024-07-28 21:08:16

jstack 使用的相关文章

定位程序问题出现的原因工具-jstack

jstack还可以生成线程快照 如何使用jstack: 1.打开命令行,输入jstack 在任务管理器中就可看到对应进程id 2.在命令行中输入 jstack -l 进程id 这样就可得到进程中所有的线程

使用jdk的jps、jstack工具检测代码问题,提高程序性能

?? 今天给大家分享怎样利用jdk的jps和jstack工具结合定位代码的问题,提高程序的稳定性.健壮性和性能. 在jdk的bin,目录下面有很多的工具如图: jps.jstack工具介绍: jps: 是JDK1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况. 命令格式:jps [options ] [ hostid ] [options]选项 : -q:仅输出VM标识符,不包括classname,jar

jstack命令详解

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题.另外,jstack工具还可以附属到正在运行的java程

java中在linux下利用jstack检测死锁

首先,编写一个死锁程序 1 package deadlock; 2 3 public class testJstack { 4 final static Object resource_1 = new Object(); 5 final static Object resource_2 = new Object(); 6 7 public static void main(String[] args) { 8 Thread t1 = new Thread("t1") { 9 publi

Java命令学习系列(二)——Jstack

jstack是java虚拟机自带的一种堆栈跟踪工具. 功能 jstack用于生成java虚拟机当前时刻的线程快照.线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁.死循环.请求外部资源导致的长时间等待等. 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源. 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的ja

Win下,通过Jstack截取Java进程中的堆栈信息

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

JStack分析cpu消耗过高问题

1. top找到目标进程,记下pid 2. top –p pid, 并用shift+h打开线程模式     这样可以看到这个进程中,到底哪个线程占用大量cpu     记下threadid,tid 3. jstack查看该线程实时的stack情况     jstack [pid]|grep -A 10 [tid(16进制)] , 10表示打印stack的长度,可以选择打印更多的stack信息    比如,jstack 21125|grep -A 10 52f1 http://www.iteye.

Java自带的性能监测工具用法简介——jstack、jconsole、jinfo、jmap、jdb、jsta、jvisualvm

JDK内置工具使用 一.javah命令(C Header and Stub File Generator) 二.jps命令(Java Virtual Machine Process Status Tool) 三.jstack命令(Java Stack Trace) 四.jstat命令(Java Virtual Machine Statistics Monitoring Tool) 五.jmap命令(Java Memory Map) 六.jinfo命令(Java Configuration Inf

jstack和线程dump分析

一:jstack jstack命令的语法格式: jstack  <pid>.可以用jps查看java进程id.这里要注意的是:1. 不同的 JAVA虚机的线程 DUMP的创建方法和文件格式是不一样的,不同的 JVM版本, dump信息也有差别.本文中,只以 SUN的 hotspot JVM 5.0_06 为例.2. 在实际运行中,往往一次 dump的信息,还不足以确认问题.建议产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性.  二:线程分析 2.1. JVM

Java线程Dump分析工具--jstack

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:      jstack [-l][F] pid      如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题.另外,jstack工具还可