如果在生产环境中调试死锁问题,调试死锁问题的正确行动计划是什么?



注意,我不是在问死锁的概念。我感兴趣的是,如果你在生产集群服务器上的java应用程序中遇到这个问题,你会怎么做,以及调试技巧。

  • 关于分析步骤计划的最佳实践。

  • 你已经知道有一台服务器遇到了这个问题。
  • 操作系统正在使用Linux

  • 你想知道根本原因并解决它
  1. 向服务器发送SIGQUIT信号以强制转储堆栈。如果您在Windows上,您可能能够使用jconsole获得类似的转储。。但是如果你在Linux上运行服务器,生活会容易得多。
  2. 检查堆栈转储以查找死锁
  3. 了解它是什么,尝试在测试服务器上复制
  4. 当你可以复制它,修复它,然后在测试服务器上测试

从Ernest的提示中找到另一个有用的链接提示。http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/

本文的一些建议。

在windows中,您可以在这里使用<ctrl><break>样本结果。

2011-08-27 19:48:38
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.2-b03 mixed mode):
"DestroyJavaVM" prio=6 tid=0x00000000003db000 nid=0x414 waiting on condition [0x
0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Thread-1" prio=6 tid=0x0000000006621800 nid=0x2178 waiting for monitor entry [0
x0000000006f8f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at SimpleDeadLock$Thread2.run(SimpleDeadLock.java:33)
        - waiting to lock <0x00000000ebc3c3e8> (a java.lang.Object)
        - locked <0x00000000ebc3c3f8> (a java.lang.Object)
"Thread-0" prio=6 tid=0x000000000661f000 nid=0x1f50 waiting for monitor entry [0
x0000000006e8f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at SimpleDeadLock$Thread1.run(SimpleDeadLock.java:20)
        - waiting to lock <0x00000000ebc3c3f8> (a java.lang.Object)
        - locked <0x00000000ebc3c3e8> (a java.lang.Object)
"Low Memory Detector" daemon prio=6 tid=0x0000000006603000 nid=0x1118 runnable [
0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x0000000006600800 nid=0x1340 waiting on
 condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x00000000065ee000 nid=0x1e10 waiting on
 condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Attach Listener" daemon prio=10 tid=0x00000000065a2800 nid=0xebc runnable [0x00
00000000000000]
   java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x000000000659d000 nid=0x18b4 waiting on
condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=8 tid=0x000000000052d800 nid=0x1b6c in Object.wait() [0x
000000000658f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000ebc01300> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x00000000ebc01300> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
"Reference Handler" daemon prio=10 tid=0x0000000000523800 nid=0x2054 in Object.w
ait() [0x000000000648f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000ebc011d8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:485)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
        - locked <0x00000000ebc011d8> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=10 tid=0x000000000051b800 nid=0x1f44 runnable
"GC task thread#0 (ParallelGC)" prio=6 tid=0x0000000000476000 nid=0x25c runnable

"GC task thread#1 (ParallelGC)" prio=6 tid=0x0000000000478800 nid=0x1ef0 runnabl
e
"GC task thread#2 (ParallelGC)" prio=6 tid=0x000000000047b000 nid=0x1d88 runnabl
e
"GC task thread#3 (ParallelGC)" prio=6 tid=0x000000000047c800 nid=0x1e3c runnabl
e
"VM Periodic Task Thread" prio=10 tid=0x000000000661c000 nid=0x1f40 waiting on c
ondition
JNI global references: 882

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000000052abb0 (object 0x00000000ebc3c3e8, a java.
lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000000052d460 (object 0x00000000ebc3c3f8, a java.
lang.Object),
  which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
        at SimpleDeadLock$Thread2.run(SimpleDeadLock.java:33)
        - waiting to lock <0x00000000ebc3c3e8> (a java.lang.Object)
        - locked <0x00000000ebc3c3f8> (a java.lang.Object)
"Thread-0":
        at SimpleDeadLock$Thread1.run(SimpleDeadLock.java:20)
        - waiting to lock <0x00000000ebc3c3f8> (a java.lang.Object)
        - locked <0x00000000ebc3c3e8> (a java.lang.Object)
Found 1 deadlock.
Heap
 PSYoungGen      total 18176K, used 937K [0x00000000ebc00000, 0x00000000ed040000
, 0x0000000100000000)
  eden space 15616K, 6% used [0x00000000ebc00000,0x00000000ebcea520,0x00000000ec
b40000)
  from space 2560K, 0% used [0x00000000ecdc0000,0x00000000ecdc0000,0x00000000ed0
40000)
  to   space 2560K, 0% used [0x00000000ecb40000,0x00000000ecb40000,0x00000000ecd
c0000)
 PSOldGen        total 41472K, used 0K [0x00000000c3400000, 0x00000000c5c80000,
0x00000000ebc00000)
  object space 41472K, 0% used [0x00000000c3400000,0x00000000c3400000,0x00000000
c5c80000)
 PSPermGen       total 21248K, used 2930K [0x00000000be200000, 0x00000000bf6c000
0, 0x00000000c3400000)
  object space 21248K, 13% used [0x00000000be200000,0x00000000be4dc9f8,0x0000000
0bf6c0000)

专家的清单

这涵盖了关于Java堆栈跟踪的理论,现在您应该知道下次看到堆栈跟踪时要查找什么了。为了节省时间,一定要充分利用jdbc bug搜索,看看您遇到的问题是否已经被报告了。

总结一下,当您下次遇到有问题的Java程序时,可以采取以下步骤:

对于挂起、死锁或冻结的程序:如果你认为你的程序挂起了,生成堆栈跟踪并检查处于MW或CW状态的线程。如果程序死锁,那么一些系统线程可能会显示为当前线程,因为JVM没有其他事情可做。

对于崩溃、中止的程序:在UNIX上查找核心文件。您可以在本地调试工具(如gdb或dbx)中分析该文件。查找调用本机方法的线程。由于Java技术使用安全内存模型,因此任何损坏都可能发生在本机代码中。请记住,JVM也使用本机代码,因此它不一定是应用程序中的错误。

对于繁忙的程序:对于繁忙的程序,您可以采取的最佳措施是生成频繁的堆栈跟踪。这将缩小导致错误的代码路径,然后您可以从那里开始调查。

祝你调试顺利

官方文章确实不错!只想和大家分享!

发送SIGQUIT的命令在不同的操作系统中会有所不同。

但这不是主要问题。

除了操作系统命令之外,我找到了另一个选项来查看线程的堆栈跟踪。这是使用jstack pid。

但是jstack目前在Windows平台或Linux Itanium平台上不可用。

甚至有一个堆栈跟踪分析工具,在一个SO帖子中找到。

有一个非常详细的一步一步的过程从这篇文章!

最新更新