Thread Dump and Concurrency Locks

Thread dumps are very useful for diagnosing synchronization related problems such as deadlocks on object monitors. Ctrl-\ on Solaris/Linux or Ctrl-Break on Windows has been a common way to get a thread dump of a running application. O n Solaris or Linux, you can send a QUIT signal to the target application. The target application in both cases prints a thread dump to the standard output and also detects if there is any deadlock involving object monitors.

jstack , a new troubleshooting utility introduced in Tiger (J2SE 5.0), provides another way to obtain a thread dump of an application. Alan Bateman has a nice blogabout jstack and its several improvements in Mustang (Java SE 6). Mustang jstack works like a remote Ctrl-\ or Ctrl-Break if you are on Windows.

jconsoleis JMX-complaint GUI tool which allows you to get a thread dump on the fly. The "Using JConsole to Monitor Applications " article gives you an overview of the Tiger monitoring and management functionality.

Mustang extends the thread dump, jstack, and jconsole to support java.util.concurrent.locks to improve its diagnosability. For example, the Threads tab in the Mustang jconsole now shows which synchronizer a thread is waiting to acquire when the thread is blocked to lock a ReentrantLock and also which thread is owning that lock.

In addition, it has a new "detect deadlock" button (in the bottom). When you click on the "detect deadlock" button, it will send a request to the target application to perform the deadlock detection operation. If the target application is running on Mustang, it finds deadlocks involving both object monitors as well as the java.util.concurrent.locks. If the target application is running on Tiger, it finds deadlocks involving object monitors only. Each deadlock cycle will be displayed in a separate Deadlock tab.

Click here to see a wider form of this screenshot.

JDK 6 has a nice demo FullThreadDump under $JDK_HOME/demo/management/FullThreadDump where JDK_HOME is the location of your JDK 6. This demo has been included in JDK 5.0 and is updated to use the new Mustang API. It demonstrates the use of the java.lang.management API to get the thread dump and detect deadlock programmatically.

中文资料:

我发现现在网上没有好好讲这个的,少数的几篇文章都是大谈自己的工具,却没把方法讲清楚。我决定以我以前碰到的case为例写一篇来分享。到目前为止,我认为分析Java代码问题的最有效的工具仍然是java thread dump。

原因:

- 任何操作系统平台下都可以使用。

- 在多数情况下,可以在生产环境中使用。

- 和操作系统提供的工具相比,java thread dump给出的信息是直白的,直接对应到应用代码。

- 它对被分析的系统干扰很小,因此能反应真实的问题。而其它很多profiling或Instrument工具本身对JVM运行有很大的干扰,经常不能暴露出真正的问题,而且这种工具不能用于生产系统。

我觉得在通常情况下分析Java虚拟机死锁比分析内存泄漏要容易的多。因为死锁发生时,JVM通常处于挂起状态(hang住了),thread dump可以给出静态稳定的信息,查找死锁只需要查找有问题的线程。而内存泄漏的问题却很难界定,一个运行的JVM里有无数对象存在,只有写程序的人才知道哪些对象是垃圾,而哪些不是,而且对象的引用关系非常复杂,很难得到一份清晰的对象引用图。

Java虚拟机死锁发生时,从操作系统上观察,虚拟机的CPU占用率为零,很快会从top或prstat的输出中消失。这时你就可以收集thread dump了,Unix/Linux 下是kill -3 <JVM pid> ,在Windows下可以在JVM的console窗口上敲Ctrl-Break。根据不同的设置,thread dump会输出到当前控制台上或应用服务器的日志里。

拿到java thread dump后,你要做的就是查找"waiting for monitor entry"的thread,如果大量thread都在等待给同一个地址上锁(因为对于Java,一个对象只有一把锁),这说明很可能死锁发生了。比如:

"service-j2ee" prio=5 tid=0x024f1c28 nid=0x125 waiting for monitor entry

[62a3e000..62a3f690]

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.IASNonSharedResourcePool.internalGetResource(IASNonS

haredResourcePool.java:625)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - waiting to

lock <0x965d8110> (a com.sun.enterprise.resource.IASNonSharedResourcePool)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.IASNonSharedResourcePool.getResource(IASNonSharedRes

ourcePool.java:520)

................

为了确定问题,常常需要在隔两分钟后再次收集一次thread dump,如果得到的输出相同,仍然是大量thread都在等待给同一个地址上锁,那么肯定是死锁了。

如何找到当前持有锁的线程是解决问题的关键。方法是搜索thread dump,查找"locked <0x965d8110>", 找到持有锁的线程。

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: "Thread-20" daemon prio=5 tid=0x01394f18

nid=0x109 runnable [6716f000..6716fc28]

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

java.net.SocketInputStream.socketRead0(Native Method)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

java.net.SocketInputStream.read(SocketInputStream.java:129)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.Packet.receive(Unknown

Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.net.ns.DataPacket.receive(Unknown Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.net.ns.NetInputStream.read(Unknown Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.net.ns.NetInputStream.read(Unknown Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.net.ns.NetInputStream.read(Unknown Source)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:929)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:893)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.jdbc.ttc7.Ocommoncall.receive(Ocommoncall.java:106)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.jdbc.ttc7.TTC7Protocol.logoff(TTC7Protocol.java:396)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f47a0> (a

oracle.jdbc.ttc7.TTC7Protocol)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

oracle.jdbc.driver.OracleConnection.close(OracleConnection.java:1518)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f4520> (a

oracle.jdbc.driver.OracleConnection)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.JdbcUrlAllocator.destroyResource(JdbcUrlAllocator.java:122)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.IASNonSharedResourcePool.destroyResource(IASNonSharedResourcePool.java:8

72)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.IASNonSharedResourcePool.resizePool(IASNonSharedResourcePool.java:1086)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x965d8110> (a

com.sun.enterprise.resource.IASNonSharedResourcePool)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

com.sun.enterprise.resource.IASNonSharedResourcePool$Resizer.run(IASNonSharedResourcePool.java:1178)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

java.util.TimerThread.mainLoop(Timer.java:432)

[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at

java.util.TimerThread.run(Timer.java:382)

在这个例子里,持有锁的线程在等待Oracle返回结果,却始终等不到响应,因此发生了死锁。

如果持有锁的线程还在等待给另一个对象上锁,那么还是按上面的办法顺藤摸瓜,直到找到死锁的根源为止。

另外,在thread dump里还会经常看到这样的线程,它们是等待一个条件而主动放弃锁的线程。例如:

"Thread-1" daemon prio=5 tid=0x014e97a8 nid=0x80 in Object.wait() [68c6f000..68c6fc28]

at java.lang.Object.wait(Native Method)

- waiting on <0x95b07178> (a java.util.LinkedList)

at com.iplanet.ias.util.collection.BlockingQueue.remove(BlockingQueue.java:258)

- locked <0x95b07178> (a java.util.LinkedList)

at com.iplanet.ias.util.threadpool.FastThreadPool$ThreadPoolThread.run(FastThreadPool.java:241)

at java.lang.Thread.run(Thread.java:534)

有时也会需要分析这类线程,尤其是线程等待的条件。

其实,Java thread dump并不只用于分析死锁,其它Java应用运行时古怪的行为都可以用thread dump来分析。

最后,在Java SE 5里,增加了jstack的工具,也可以获取thread dump。在Java SE 6里, 通过jconsole的图形化工具也可以方便地查找涉及object monitors 和java.util.concurrent.locks死锁。

如何分析Java虚拟机死锁的更多相关文章

  1. Java虚拟机(二)对象的创建与OOP-Klass模型

    前言 在前一篇文章中我们学习了Java虚拟机的结构原理与运行时数据区域,那么我们大概知道了Java虚拟机的内存的概况,那么内存中的数据是如何创建和访问的呢?这篇文章会给你答案. 1.对象的创建 对象的 ...

  2. Java虚拟机性能管理神器 - VisualVM(1) 简介 - JVM轻量级监控分析神器

    目录(?)[-] 一VisualVM是什么 二如何获取VisualVM 三获取那个版本 四VisualVM能做什么 显示JAVA应用程序配置和运行时环境 显示本地和远程JAVA应用程序运行状态 监控应 ...

  3. Java虚拟机详解(七)------虚拟机监控和分析工具(1)——命令行

    通过前面的几篇博客,我们介绍了Java虚拟机的内存分配以及内存回收等理论知识,了解这些知识对于我们在实际生产环境中提高系统的运行效率是有很大的帮助的.但是话又说回来,在实际生产环境中,线上项目正在运行 ...

  4. Java虚拟机性能管理神器 - VisualVM(9) 排查JAVA应用程序线程死锁【转】

    Java虚拟机性能管理神器 - VisualVM(9) 排查JAVA应用程序线程死锁[转] 标签: javajvm监控工具性能优化 2015-03-11 19:59 1948人阅读 评论(0) 收藏  ...

  5. java虚拟机(十)--性能监控工具测试内存溢出和死锁基本思路

    在之前就曾经简单介绍过jdk自带的性能检测工具,但是只是很入门的内容.没有真正的用过都是白扯了,面试的时候也说不过去,更别提真正 在生产环境去解决问题,所以这里我们学习一下真正解决问题的过程,最起码面 ...

  6. 《深入理解Java虚拟机》调优案例分析与实战

    上节学习回顾 在上一节当中,主要学习了Sun JDK的一些命令行和可视化性能监控工具的具体使用,但性能分析的重点还是在解决问题的思路上面,没有好的思路,再好的工具也无补于事. 本节学习重点 在书本上本 ...

  7. Java虚拟机类加载机制——案例分析

    转载: Java虚拟机类加载机制--案例分析   在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...

  8. Java虚拟机三:OutOfMemoryError异常分析

    根据Java虚拟机规范,虚拟机内存中除过程序计数器之外的运行时数据区域都会发生OutOfMemoryError(OOM),本文将通过实际例子验证分析各个数据区域OOM的情况.为了更贴近生产,本次所有例 ...

  9. 《深入理解Java虚拟机》-----第5章 jvm调优案例分析与实战

    案例分析 高性能硬件上的程序部署策略 例 如 ,一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU.16GB物理内存,操作系统为64位CentOS 5.4 , Resin ...

随机推荐

  1. HDU 4708 Rotation Lock Puzzle (简单题)

    Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  2. Windows程序调试系列: 使用VC++生成调试信息 转

    Windows程序调试系列: 使用VC++生成调试信息 ZhangTao,zhangtao.it@gmail.com, 译自 “Generating debug information with Vi ...

  3. StringBuilder和StringBuffer解析(百度面试题优化须要用到的)

    StringBuilder是java5及以后提供的API,它不是线程安全的,而StringBuffer是java1.4曾经的API,它是线程安全的,所以说StringBuilder的效率更高一些,今天 ...

  4. andriod 获得MP4时长

    //获得MP4时长 private int getTimeLong(String videoPath) { MediaMetadataRetriever retr = new MediaMetadat ...

  5. SQL 条件 判断 select case as

    " then "返回的数据1" " then "返回的数据2" else "返回的其他数据" end as 新的列名 f ...

  6. TQ2440实现触摸屏和qt图形 解决segmentation fault

    使用触摸屏,首先安装触摸屏矫正程序. 下载并解压tslib-1.4,进入主文件夹,运行: 1 [root@localhost ~]#./autogen.sh 2 [root@localhost ~]# ...

  7. 莫比乌斯函数&莫比乌斯反演

    莫比乌斯函数:http://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html Orz  PoPoQQQ

  8. HDU 4864 Task(贪心)

    HDU 4864 Task 题目链接 题意:有一些机器和一些任务.都有时间和等级,机器能做任务的条件为时间等级都大于等于任务.而且一个任务仅仅能被一个机器做.如今求最大能完毕任务.而且保证金钱尽量多 ...

  9. [13] 弧面(Arc)图形的生成算法

    顶点数据的生成 bool YfBuildArcVertices ( Yreal radius, Yreal degree, Yreal height, Yuint slices, Yuint stac ...

  10. [置顶] Django 微信开发(一)——环境搭建

    Django 微信开发(一)——环境搭建 随着移动互联网时代的到来,微信——一个改变着我们生活的产品悄悄走近了我们的生活.我们不得不觉得自己很幸运,自己能在这个世界上遇到像QQ.微博.微信这样优秀的产 ...