JDK自带工具之jstack

jstackjava虚拟机自带的一种堆栈跟踪工具。jstack位于javabin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。

Jstat可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。

1、Jstack命令格式

jstack [ option ] pid

2、常用参数

-F’jstack [-l] pid’没有相应的时候强制打印栈信息

-l长列表打印关于锁的附加信息,例如属于java.util.concurrentownable synchronizers列表.

-m打印javanative c/c++框架的所有栈信息.

-h | -help打印帮助信息

pid 需要被打印配置信息的java进程id,可以用jps查询.

 

3、生成死锁(deadlock)的源代码

package com.jdkTools;

 

/**

 * 简单的应用,供测试JDK自带的jstack使用 本应用会造成deadlock,可能会导致系统崩溃

 * 逻辑:一旦两个线程互相等待的局面出现,死锁(deadlock)就发生了

 *

 * @author 范芳铭

 */

public class EasyJstack extends Thread {

    private EasyJstackResourceresourceManger;//资源管理类的私有引用,通过此引用可以通过其相关接口对资源进行读写

    private int a, b;// 将要写入资源的数据

 

    public static void main(String[]args) throws Exception {

        EasyJstackResourceresourceManager = new EasyJstackResource();

        EasyJstack stack1 = newEasyJstack(resourceManager, 1, 2);

        EasyJstack stack2 = newEasyJstack(resourceManager, 3, 4);

 

        stack1.start();

        stack2.start();

 

    }

 

    publicEasyJstack(EasyJstackResource resourceManager, int a, int b) {

        this.resourceManger =resourceManager;

        this.a = a;

        this.b = b;

    }

 

    public void run() {

        while (true) {

            this.resourceManger.read();

            this.resourceManger.write(this.a,this.b);

        }

    }

}

 

package com.jdkTools;

/**

 * 简单的应用,供测试JDK自带的jstack使用 本应用会造成deadlock,可能会导致系统崩溃

 * 逻辑:一旦两个线程互相等待的局面出现,死锁(deadlock)就发生了

 * @author 范芳铭

 */

public class EasyJstackResource {

    /**

     * 管理的两个资源,如果有多个线程并发,那么就会死锁

     */

    private Resource resourceA = newResource();

    private Resource resourceB = newResource();

 

    public EasyJstackResource() {

        this.resourceA.setValue(0);

        this.resourceB.setValue(0);

    }

 

    public int read() {

        synchronized (this.resourceA){

            System.out.println(Thread.currentThread().getName()

                    + "线程拿到了资源 resourceA的对象锁");

            synchronized (resourceB){

                System.out.println(Thread.currentThread().getName()

                        + "线程拿到了资源 resourceB的对象锁");

                return this.resourceA.getValue()+ this.resourceB.getValue();

            }

        }

    }

 

    public void write(int a, int b) {

        synchronized (this.resourceB){

            System.out.println(Thread.currentThread().getName()

                    + "线程拿到了资源 resourceB的对象锁");

            synchronized(this.resourceA) {

                System.out.println(Thread.currentThread().getName()

                        + "线程拿到了资源 resourceA的对象锁");

                this.resourceA.setValue(a);

                this.resourceB.setValue(b);

            }

        }

    }

 

    public class Resource {

        private int value;// 资源的属性

 

        public int getValue() {

            return value;

        }

 

        public void setValue(intvalue) {

            this.value = value;

        }

    }

}

4、运行结果

Thread-0线程拿到了资源 resourceA 的对象锁

Thread-0线程拿到了资源 resourceB 的对象锁

Thread-0线程拿到了资源 resourceB 的对象锁

Thread-1线程拿到了资源 resourceA 的对象锁

 

应用已经被锁住了

 

5、用jstack进行分析

C:\Program Files\Java\jdk1.6.0_25\bin>jps -l

5204 com.jdkTools.EasyJstack

6268 sun.tools.jps.Jps

5412

 

C:\Program Files\Java\jdk1.6.0_25\bin>jstack 5204

2015-01-21 15:32:22

Full thread dump Java HotSpot(TM) Client VM (11.3-b02mixed mode):

中间省略

"Signal Dispatcher" daemon prio=10tid=0x01a42000 nid=0x1a5c runnable [0x00000000..0x00000000]

  java.lang.Thread.State: RUNNABLE

 

"Finalizer" daemon prio=8 tid=0x01a2b000nid=0x1798 in Object.wait() [0x0bc3f000..0x0bc3fa68]

  java.lang.Thread.State: WAITING (on object monitor)

        atjava.lang.Object.wait(Native Method)

        - waitingon <0x03b50b38> (a java.lang.ref.ReferenceQueue$Lock)

        atjava.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)

        - locked<0x03b50b38> (a java.lang.ref.ReferenceQueue$Lock)

        atjava.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)

        atjava.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

 

"Reference Handler" daemon prio=10tid=0x01a29c00 nid=0x1e38 in Object.wait() [0x0bbef000..0x0bbefae8]

  java.lang.Thread.State: WAITING (on object monitor)

        atjava.lang.Object.wait(Native Method)

        - waitingon <0x03b50a40> (a java.lang.ref.Reference$Lock)

        atjava.lang.Object.wait(Object.java:485)

        atjava.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)

        - locked<0x03b50a40> (a java.lang.ref.Reference$Lock)

 

"VM Thread" prio=10 tid=0x01a26800 nid=0x1cecrunnable

 

"VM Periodic Task Thread" prio=10tid=0x01a80000 nid=0x10e0 waiting on condition

 

JNI global references: 594

 

 

Found one Java-level deadlock:

=============================

"Thread-1":

  waiting to lockmonitor 0x01a2dea4 (object 0x03b8ed40, acom.jdkTools.EasyJstackResource$Resource),

  which is held by"Thread-0"

"Thread-0":

  waiting to lockmonitor 0x01a2eb3c (object 0x03b8ed30, acom.jdkTools.EasyJstackResource$Resource),

  which is held by"Thread-1"

 

Java stack information for the threads listed above:

===================================================

"Thread-1":

        atcom.jdkTools.EasyJstackResource.read(EasyJstackResource.java:27)

        - waitingto lock <0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

        - locked<0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

        atcom.jdkTools.EasyJstack.run(EasyJstack.java:34)

"Thread-0":

        atcom.jdkTools.EasyJstackResource.write(EasyJstackResource.java:42)

        - waitingto lock <0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

        - locked<0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

        atcom.jdkTools.EasyJstack.run(EasyJstack.java:35)

 

Found 1 deadlock.

 

能够明确看到“Found one Java-level deadlock:”能够找到系统中的死锁。

 

6、分析结果

Java stack information for the threads listed above:

===================================================

"Thread-1":

        atcom.jdkTools.EasyJstackResource.read(EasyJstackResource.java:27)

        - waitingto lock <0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

        - locked<0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

        atcom.jdkTools.EasyJstack.run(EasyJstack.java:34)

"Thread-0":

        atcom.jdkTools.EasyJstackResource.write(EasyJstackResource.java:42)

        - waitingto lock <0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)

        - locked<0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)

        atcom.jdkTools.EasyJstack.run(EasyJstack.java:35)

 

Found 1 deadlock.

仔细看这一段文字,告诉我们 EasyJstackResource.java:27出了状况。如果出现了这种情况,我们就要从这里开始顺藤摸瓜,解决问题。

 

7、其他状态和简单解读

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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。