怎样使用jstack诊断Java应用程序故障(转)

最近一段时间,我们的生产系统升级频繁出现故障,具体故障现象是启动后10来分钟就出现交易缓慢,处理线程耗尽等现象,并且故障发生的频率蛮高的。经过详细的诊断和排查,终于发现了问题,是groovy在osgi中运行会出现classloader死锁,最后我们也解决了这个问题。 
        如果单靠通过查看代码是很难去发现这个问题,在这一次故障排查中,我也学到了怎样更好的使用jvm监控工具来进行诊断,主要用到了jstack和jmap命令,jmap上次已经讲过就不再讲了,下面就一个例子来讲怎么使用jstack来对的Java程序进行诊断。 
        首先让我们来了解一下jstack这个命令的作用,jstack 是一个可以返回在应用程序上运行的各种各样线程的一个完整转储的实用程序,您可以使用它查明问题。jstack [-l] <pid>,jpid可以通过使用jps命令来查看当前Java程序的jpid值,-l是可选参数,它可以显示线程阻塞/死锁情况。

/**
 * 死锁例子
 */
public class DeadLock {

    public static void main(String[] args) {
        final Object obj_1 = new Object(), obj_2 = new Object();

        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                synchronized (obj_1) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {}

                    synchronized (obj_2) {
                        System.out.println("thread t1 done.");
                    }
                }
            }
        };

        Thread t2 = new Thread("t2"){
            @Override
            public void run() {
                synchronized (obj_2) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {}

                    synchronized (obj_1) {
                        System.out.println("thread t2 done.");
                    }
                }
            }
        };

        t1.start();
        t2.start();
    }

}

以上DeadLock类是一个死锁的例子,假使在我们不知情的情况下,运行DeadLock后,发现等了N久都没有在屏幕打印线程完成信息。这个时候我们就可以使用jps查看该程序的jpid值和使用jstack来生产堆栈结果问题。

$ java -cp deadlock.jar DeadLock &
$ 
$ jps
  3076 Jps
  448 DeadLock
$ jstack -l 448 > deadlock.jstack

结果文件deadlock.jstack内容如下:

2011-03-20 23:05:20
Full thread dump Java HotSpot(TM) Client VM (19.1-b02 mixed mode, sharing):

"DestroyJavaVM" prio=6 tid=0x00316800 nid=0x9fc waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"t2" prio=6 tid=0x02bcf000 nid=0xc70 waiting for monitor entry [0x02f6f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.demo.DeadLock$2.run(DeadLock.java:40)
    - waiting to lock <0x22a297a8> (a java.lang.Object)
    - locked <0x22a297b0> (a java.lang.Object)

   Locked ownable synchronizers:
    - None

"t1" prio=6 tid=0x02bce400 nid=0xba0 waiting for monitor entry [0x02f1f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.demo.DeadLock$1.run(DeadLock.java:25)
    - waiting to lock <0x22a297b0> (a java.lang.Object)
    - locked <0x22a297a8> (a java.lang.Object)

   Locked ownable synchronizers:
    - None

"Low Memory Detector" daemon prio=6 tid=0x02bb9400 nid=0xa6c runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"CompilerThread0" daemon prio=10 tid=0x02bb2800 nid=0xcb8 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Attach Listener" daemon prio=10 tid=0x02bb1000 nid=0x7f4 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Signal Dispatcher" daemon prio=10 tid=0x02bd2800 nid=0xd80 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Finalizer" daemon prio=8 tid=0x02bab000 nid=0xe1c in Object.wait() [0x02d3f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
    - locked <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

   Locked ownable synchronizers:
    - None

"Reference Handler" daemon prio=10 tid=0x02ba6800 nid=0xbe0 in Object.wait() [0x02cef000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x229e1048> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:485)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
    - locked <0x229e1048> (a java.lang.ref.Reference$Lock)

   Locked ownable synchronizers:
    - None

"VM Thread" prio=10 tid=0x02b6a400 nid=0x568 runnable 

"VM Periodic Task Thread" prio=10 tid=0x02bc8400 nid=0x75c waiting on condition 

JNI global references: 878

Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x02baaeec (object 0x22a297a8, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x02baa2bc (object 0x22a297b0, a java.lang.Object),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
    at com.demo.DeadLock$2.run(DeadLock.java:40)
    - waiting to lock <0x22a297a8> (a java.lang.Object)
    - locked <0x22a297b0> (a java.lang.Object)
"t1":
    at com.demo.DeadLock$1.run(DeadLock.java:25)
    - waiting to lock <0x22a297b0> (a java.lang.Object)
    - locked <0x22a297a8> (a java.lang.Object)

Found 1 deadlock.

从这个结果文件我们一看到发现了一个死锁,具体是线程t2在等待线程t1,而线程t1在等待线程t2造成的,同时也记录了线程的堆栈和代码行数,通过这个堆栈和行数我们就可以去检查对应的代码块,从而发现问题和解决问题。

http://crane-ding.iteye.com/blog/968862

时间: 2024-10-26 23:48:44

怎样使用jstack诊断Java应用程序故障(转)的相关文章

Java应用程序高CPU故障诊断(troubleshooting)思路

系统运行出现高CPU报警,一般可以通过top或者任务管理器找到哪些进程在使用CPU,但这个粒度不能让我们知道得更多,我们需要找到程序的哪部分在占用CPU并且在占用CPU做什么,这样才有利于我们以后调优,下面介绍一种可行的思路: 找到占用CPU高的进程p 找到进程p中占用CPU高的线程t 找到线程t在做什么 本文以Linux下Java应用程序为例,其他环境或程序可参照该思路,只要思路清晰就好办了 打开top,在top中按shift+p按照CPU使用量倒序显示进程,找到占用CPU较高的进程号pid,

jstack命令(Java Stack Trace)

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

10本Java精选书籍助你快速进阶Java顶尖程序员

书是人类进步的阶梯,从某种意义上讲,一个人读书多少,跟这个人将来能有多大成就取得多大成功有着必然的联系,然而读书不仅仅是求量的过程,还需要精读.有选择的读,前面的文章给大家介绍过从零基础学习java编程到精通之路的五本书籍,但是Java学习入门之后,想要往更高层次的Java方向发展,如果能有几本好书的辅助,可以使我们在Java进阶之路上事半功倍,那么下面亦是美网络小编再给大家推荐10本Java精选书籍助你进阶Java顶尖程序员. 1.<深入理解Java虚拟机:JVM高级特性与最佳实践> 本书从

在 Linux 上创建第一个 Service Fabric Java 应用程序

先决条件 开始之前,请安装 Service Fabric SDK.Azure CLI,并在 Linux 开发环境中设置开发群集. 如果使用 Mac OS X,则可使用 Vagrant 在虚拟机中设置 Linux 开发环境. 此外还需配置 Azure CLI 2.0(推荐)或 XPlat CLI,以便部署应用程序. 创建应用程序 Service Fabric 应用程序包含一个或多个服务,每个服务都在提供应用程序功能时具有特定角色. 适用于 Linux 的 Service Fabric SDK 包含

java web 程序---购物车选商品,购买,付款

虚函数使用的时机 为什么虚函数不总是适用? 1. 虚函数有事会带来很大的消耗: 2. 虚函数不总是提供所需的行为: 3. 当我们不考虑继承当前类时,不必使用虚函数. 必须使用虚函数的情况: 1. 当你想删除一个表面上指向基类对象,实际却是指向派生类对象的指针,就需要虚析构函数. java web 程序---购物车选商品,购买,付款,布布扣,bubuko.com

解决 GTK+/GNOME 3 环境下 Java Swing 程序使用本地 GTK+ 主题时菜单无边框 bug 的方法

在 GTK+/GNOME 3 环境下采用默认的 Adwaita 主题时,Java Swing 程序如果使用本地 GTK+ 主题会出现菜单无边框的 bug,这个问题也可能在其他常用的 GTK+ 主题中出现.说这是 Java Swing 的 bug 还是 GTK+/GNOME 3 的主题(如 Adwaita)的 bug 其实意义不是太大.这里给出一个简单的解决办法,其思路是修改 GTK+/GNOME 3 的主题,这里以系统默认的 Adwaita 主题为例: Adwaita 主题文件位于 /usr/s

JAVA基础-输入输出:1.编写TextRw.java的Java应用程序,程序完成的功能是:首先向TextRw.txt中写入自己的学号和姓名,读取TextRw.txt中信息并将其显示在屏幕上。

1.编写TextRw.java的Java应用程序,程序完成的功能是:首先向TextRw.txt中写入自己的学号和姓名,读取TextRw.txt中信息并将其显示在屏幕上. package Test03; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOExceptio

Java基础-接口中国特色社会主义的体制中有这样的现象:地方省政府要坚持党的领导和按 照国务院的指示进行安全生产。请编写一个java应用程序描述上述的体制现象。 要求如下: (1)该应用程序中有一个“党中央”接口:CentralPartyCommittee,该接口中 有个“坚持党的领导”方法:void partyLeader() (2)该应用程序中有一个“国务院”抽象类:StateCouncil,

36.中国特色社会主义的体制中有这样的现象:地方省政府要坚持党的领导和按 照国务院的指示进行安全生产.请编写一个java应用程序描述上述的体制现象. 要求如下: (1)该应用程序中有一个“党中央”接口:CentralPartyCommittee,该接口中 有个“坚持党的领导”方法:void partyLeader() (2)该应用程序中有一个“国务院”抽象类:StateCouncil,该抽象类中有个“安 全生产”的抽象方法:abstract void safetyInProduction() (

java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E

21.编写一个Java应用程序,该程序包括3个类:Monkey类.People类和主类 E.要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public void speak() 方法,在speak方法中输出“咿咿呀呀......”的信息. (2)People类是Monkey类的子类,在People类中重写方法speak(),在speak方法 中输出“小样的,不错嘛!会说话了!”的信息. (3)在People类中新增方法void think(),在thi