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

本文介绍如何使用jstack命令诊断Java程序中的死锁问题,并通过一个示例展示了如何定位并解决由线程相互等待导致的死锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近一段时间,我们的生产系统升级频繁出现故障,具体故障现象是启动后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. public class DeadLock {?
  7. public static void main(String[] args) {?
  8. final Object obj_1 = new Object(), obj_2 = new Object();?
  9. ??????? Thread t1 = new Thread("t1"){?
  10. @Override
  11. public void 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. public void 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=6 tid=0x00316800 nid=0x9fc waiting on condition [0x00000000]?
  4. ?? java.lang.Thread.State: RUNNABLE?
  5. ?? Locked ownable synchronizers:?
  6. ??? - None?
  7. "t2" prio=6 tid=0x02bcf000 nid=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=6 tid=0x02bce400 nid=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=6 tid=0x02bb9400 nid=0xa6c runnable [0x00000000]?
  22. ?? java.lang.Thread.State: RUNNABLE?
  23. ?? Locked ownable synchronizers:?
  24. ??? - None?
  25. "CompilerThread0" daemon prio=10 tid=0x02bb2800 nid=0xcb8 waiting on condition [0x00000000]?
  26. ?? java.lang.Thread.State: RUNNABLE?
  27. ?? Locked ownable synchronizers:?
  28. ??? - None?
  29. "Attach Listener" daemon prio=10 tid=0x02bb1000 nid=0x7f4 waiting on condition [0x00000000]?
  30. ?? java.lang.Thread.State: RUNNABLE?
  31. ?? Locked ownable synchronizers:?
  32. ??? - None?
  33. "Signal Dispatcher" daemon prio=10 tid=0x02bd2800 nid=0xd80 runnable [0x00000000]?
  34. ?? java.lang.Thread.State: RUNNABLE?
  35. ?? Locked ownable synchronizers:?
  36. ??? - None?
  37. "Finalizer" daemon prio=8 tid=0x02bab000 nid=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=10 tid=0x02ba6800 nid=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=10 tid=0x02b6a400 nid=0x568 runnable??
  57. "VM Periodic Task Thread" prio=10 tid=0x02bc8400 nid=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造成的,同时也记录了线程的堆栈和代码行数,通过这个堆栈和行数我们就可以去检查对应的代码块,从而发现问题和解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值