如果在生产环境中出现死锁问题,应采取哪些适当的调试行动计划?

5

请注意,我不是在询问死锁的概念,我想知道如果您在生产集群服务器上的Java应用程序中遇到此问题以及调试技巧,您将会怎么做。

问题

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

假设

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

目标

  • 您希望找出根本原因并解决它。
3个回答

4
  1. 发送SIGQUIT信号以强制进行堆栈转储。如果您使用的是Windows,则可能可以使用jconsole获取可比较的转储。也许。但如果你在Linux上运行服务器,那么生活会容易得多。
  2. 检查堆栈转储以找到死锁
  3. 知道了死锁是什么,尝试在测试服务器上重现
  4. 当您能够重现它时,请修复它,然后在测试服务器上进行测试

除了使用操作系统命令之外,还可以做些什么来查看问题。或者已经足够了解根本原因。 - Clark Bao
1
如果您有堆栈转储,您可以看到死锁——所有所需信息都在那里。至于绝对的根本原因——即它是否只是一个局部问题,还是一个重大的架构问题——这是您必须从代码中阅读的内容。真的没有配方。您可以看到死锁发生的位置,但“根本原因”——即“为什么”——通常没有绝对的答案。代码需要更改,而解决问题的人的技能和经验则取决于识别最佳修复方式。 - Ernest Friedman-Hill

1

根据欧内斯特的提示,找到了另一个有用的链接提示。

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堆栈跟踪的理论,您现在应该知道下次看到它时要寻找什么。为了节省时间,请确保充分利用JDC错误搜索功能,以查看您遇到的问题是否已经被报告。

总之,下次遇到问题Java程序时,请执行以下步骤:

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

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

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

祝你好运,愉快的调试

确实是一篇不错的官方文章!只是想与您分享!

发送SIGQUIT命令在不同的操作系统中可能会有所不同,但这不是主要问题。


0

我找到了另一种查看线程堆栈跟踪的方法,而不是使用操作系统命令。那就是使用jstack pid。

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

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

这篇文章还提供了非常详细的逐步过程!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接