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

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

 

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

Java代码 复制代码 收藏代码
  1. /**
  2. * 死锁例子
  3. * @author crane.ding
  4. * @since 2011-3-20
  5. */
  6. publicclass DeadLock {
  7. publicstaticvoid main(String[] args) {
  8. final Object obj_1 = new Object(), obj_2 = new Object();
  9. Thread t1 = new Thread("t1"){
  10. @Override
  11. publicvoid run() {
  12. synchronized (obj_1) {
  13. try {
  14. Thread.sleep(3000);
  15. } catch (InterruptedException e) {}
  16. synchronized (obj_2) {
  17. System.out.println("thread t1 done.");
  18. }
  19. }
  20. }
  21. };
  22. Thread t2 = new Thread("t2"){
  23. @Override
  24. publicvoid run() {
  25. synchronized (obj_2) {
  26. try {
  27. Thread.sleep(3000);
  28. } catch (InterruptedException e) {}
  29. synchronized (obj_1) {
  30. System.out.println("thread t2 done.");
  31. }
  32. }
  33. }
  34. };
  35. t1.start();
  36. t2.start();
  37. }
  38. }


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

Linux代码 复制代码 收藏代码
  1. $ java -cp deadlock.jar DeadLock &
  2. $


 

Linux代码 复制代码 收藏代码
  1. $ jps
  2. 3076 Jps
  3. 448 DeadLock
  4. $ jstack -l 448 > deadlock.jstack


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

Xml代码 复制代码 收藏代码
  1. 2011-03-20 23:05:20
  2. Full thread dump Java HotSpot(TM) Client VM (19.1-b02 mixed mode, sharing):
  3. "DestroyJavaVM" prio=6tid=0x00316800nid=0x9fc waiting on condition [0x00000000]
  4. java.lang.Thread.State: RUNNABLE
  5. Locked ownable synchronizers:
  6. - None
  7. "t2" prio=6tid=0x02bcf000nid=0xc70 waiting for monitor entry [0x02f6f000]
  8. java.lang.Thread.State: BLOCKED (on object monitor)
  9. at com.demo.DeadLock$2.run(DeadLock.java:40)
  10. - waiting to lock <0x22a297a8> (a java.lang.Object)
  11. - locked <0x22a297b0> (a java.lang.Object)
  12. Locked ownable synchronizers:
  13. - None
  14. "t1" prio=6tid=0x02bce400nid=0xba0 waiting for monitor entry [0x02f1f000]
  15. java.lang.Thread.State: BLOCKED (on object monitor)
  16. at com.demo.DeadLock$1.run(DeadLock.java:25)
  17. - waiting to lock <0x22a297b0> (a java.lang.Object)
  18. - locked <0x22a297a8> (a java.lang.Object)
  19. Locked ownable synchronizers:
  20. - None
  21. "Low Memory Detector" daemon prio=6tid=0x02bb9400nid=0xa6c runnable [0x00000000]
  22. java.lang.Thread.State: RUNNABLE
  23. Locked ownable synchronizers:
  24. - None
  25. "CompilerThread0" daemon prio=10tid=0x02bb2800nid=0xcb8 waiting on condition [0x00000000]
  26. java.lang.Thread.State: RUNNABLE
  27. Locked ownable synchronizers:
  28. - None
  29. "Attach Listener" daemon prio=10tid=0x02bb1000nid=0x7f4 waiting on condition [0x00000000]
  30. java.lang.Thread.State: RUNNABLE
  31. Locked ownable synchronizers:
  32. - None
  33. "Signal Dispatcher" daemon prio=10tid=0x02bd2800nid=0xd80 runnable [0x00000000]
  34. java.lang.Thread.State: RUNNABLE
  35. Locked ownable synchronizers:
  36. - None
  37. "Finalizer" daemon prio=8tid=0x02bab000nid=0xe1c in Object.wait() [0x02d3f000]
  38. java.lang.Thread.State: WAITING (on object monitor)
  39. at java.lang.Object.wait(Native Method)
  40. - waiting on <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
  41. at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
  42. - locked <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
  43. at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
  44. at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
  45. Locked ownable synchronizers:
  46. - None
  47. "Reference Handler" daemon prio=10tid=0x02ba6800nid=0xbe0 in Object.wait() [0x02cef000]
  48. java.lang.Thread.State: WAITING (on object monitor)
  49. at java.lang.Object.wait(Native Method)
  50. - waiting on <0x229e1048> (a java.lang.ref.Reference$Lock)
  51. at java.lang.Object.wait(Object.java:485)
  52. at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
  53. - locked <0x229e1048> (a java.lang.ref.Reference$Lock)
  54. Locked ownable synchronizers:
  55. - None
  56. "VM Thread" prio=10tid=0x02b6a400nid=0x568 runnable
  57. "VM Periodic Task Thread" prio=10tid=0x02bc8400nid=0x75c waiting on condition
  58. JNI global references: 878
  59. Found one Java-level deadlock:
  60. =============================
  61. "t2":
  62. waiting to lock monitor 0x02baaeec (object 0x22a297a8, a java.lang.Object),
  63. which is held by "t1"
  64. "t1":
  65. waiting to lock monitor 0x02baa2bc (object 0x22a297b0, a java.lang.Object),
  66. which is held by "t2"
  67. Java stack information for the threads listed above:
  68. ===================================================
  69. "t2":
  70. at com.demo.DeadLock$2.run(DeadLock.java:40)
  71. - waiting to lock <0x22a297a8> (a java.lang.Object)
  72. - locked <0x22a297b0> (a java.lang.Object)
  73. "t1":
  74. at com.demo.DeadLock$1.run(DeadLock.java:25)
  75. - waiting to lock <0x22a297b0> (a java.lang.Object)
  76. - locked <0x22a297a8> (a java.lang.Object)
  77. Found 1 deadlock.


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

你可能感兴趣的:(jstack)