原本也没听说过ThreadDump的概念,直到前天,公司的BOPS系统老是OutOfMemory,后来通过ThreadDump,高手们才找到了原因。我在想,ThreadDump肯定是个了不起的东东,于是网上学习了解了一下,并自己本机尝试了将ThreadDump信息打印了出来。
Thread Dump是非常有用的诊断Java应用问题的工具,每一个Java虚拟机都有及时生成显示所有线程在某一点状态的thread-dump的能力。虽然各个 Java虚拟机thread dump打印输出格式上略微有一些不同,但是Thread dumps出来的信息包含线程;线程的运行状态、标识和调用的堆栈;调用的堆栈包含完整的类名,所执行的方法,如果可能的话还有源代码的行数。
Thread Dump特点:
能在各种操作系统下使用;能在各种Java应用服务器下使用 ;可以在生产环境下使用而不影响系统的性能;可以将问题直接定位到应用程序的代码行上 。
Thread Dump能诊断的问题包括:
查找内存泄露,常见的是程序里load大量的数据到缓存;发现死锁线程 。
产生ThreadDump堆栈信息的方法:
1. UNIX/Linux
Kill -3 PID
PID通过下面方法获取
ps -efHl | grep 'java' **. **
2. Windows
直接对MSDOS窗口的程序按Ctrl-break
Sun JVM的常见线程状态:
对于thread dump信息,主要关注的是线程的状态和其执行堆栈
线程的状态一般为三类
Runnable(R):当前可以运行的线程
Waiting on monitor(CW):线程主动wait
Waiting for monitor entry(MW):线程等锁
一般关注的都是第一和第三种状态的线程
Cpu很忙则关注runnable的线程
Cpu闲则关注waiting for monitor entry的线程
如何分析Java虚拟机死锁
中文资料:
我发现现在网上没有好好讲这个的,少数的几篇文章都是大谈自己的工具,却没把方法讲清楚。我决定以我以前碰到的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死锁。
参考文档:
http://lzmhehe.javaeye.com/blog/335526
http://sesame.javaeye.com/blog/428012
http://renyongjie668.blog.163.com/blog/static/160053120101614225819/
分享到:
相关推荐
**TDA - Thread Dump Analyzer简介** TDA是一款强大的开源工具,专为Java开发者设计,用于解析和分析线程dump日志。线程dump是Java虚拟机(JVM)在特定时间点捕获的当前所有线程的状态快照,包括每个线程的堆栈跟踪...
线程转储(Thread Dump)分析工具是一款针对Java应用程序的实用工具,主要用于诊断和解决性能问题,特别是与线程相关的复杂问题。它提供了一个Web界面,使得开发者和系统管理员能够远程分析应用程序的线程状态,查找...
**TDA - Thread Dump Analyzer的简介** `TDA`全称为Thread Dump Analyzer,是一款开源的Java线程分析工具,它的主要功能是对Java应用程序产生的线程转储(Thread Dump)文件进行解析、分析和可视化。线程转储包含了...
### JVisualVM简介 JVisualVM是Java平台的一个强大的可视化工具,它可以帮助开发者监测和调试应用程序的性能问题,特别是那些与内存管理相关的故障。作为NetBeans的一个子项目,JVisualVM自JDK 1.8起就已经被集成到...
#### 二、JStack简介 `JStack`是Java Development Kit (JDK)的一部分,用于生成正在运行的Java应用程序的线程快照。这些快照提供了关于每个线程正在做什么以及它们所处的状态等信息。这对于诊断线程挂起、死锁和...
3.1 ulog简介 RT-THREAD ULOG是一个轻量级、高性能的日志框架,它支持多模块、多级别、多输出目的地,可以满足不同需求的日志管理。 3.2 ulog框架总览 ULOG框架包括日志的定义、级别控制、输出接口、标签管理和格式...
- **Who**:标识了报告该错误的来源,如特定的会话(Session)或线程(Thread)等。 - **When**:记录了错误发生的具体时间。 - **Where**:指出了错误发生的位置,包括可能的文件名及行号等信息。 #### 2. 故障...
"Thread Dump"功能可获取当前所有线程的快照,帮助分析线程问题。 #### GC日志分析 在"Garbage Collector"选项卡,导入GC日志文件,分析GC活动,优化GC设置以减少暂停时间。 #### SQL性能优化 在"Database"模块...
3.2.2. ThreadDump:用于生成Java线程快照,分析线程状态,识别死锁和线程阻塞问题。 3.2.3. JProfiler:功能强大的全栈性能分析工具,包括CPU、内存、线程、数据库等多方面的监控和分析。 3.2.4. JCA401:Java通信...
- **Executor Thread Dump Page** 这些页面提供了对正在运行的Spark应用的深入洞察,帮助用户更好地理解程序的行为和性能。 #### 四、Spark UI监听器 **Spark UI**还包含一系列监听器,用于收集和展示各种运行时...
一、JDK 命令简介 JDK 中提供了许多实用的命令,包括 javac、java、javah、jdb 等。这些命令可以帮助开发者更好地学习和使用 Java 语言。 二、javac 命令 javac 命令是 Java 源代码编译器,用于将 Java 源代码...
功能说明一键式收集Java进程的问题定位信息,包括:Thread Stack和Heap Dump等。监控Java进程使用的CPU,当占用率过高时,自动收集Top信息和Thread Stack。启动、停止、查询、导出飞行记录。使用方法将工具上传到...
- **注意事项**:如果一个主服务器连接了多个从服务器,则主服务器上会为每个从服务器运行一个Binlog Dump Thread。 #### 四、如何提高主从复制的效率 1. **优化Binary Log**:合理配置Binary Log格式和大小,...
【简介】 快手W.QQ2012,采用腾讯QQ之w.qq.com协议(手机网页版)。 【目的】 1、第一次尝试Web UI开发应用 2、进阶学习快手 3、制作QQ机器人,应用于PHP或者直接数据库交互 【分享包】 1、快手项目包(aau...
4. 高级用法:sqlmap提供了丰富的参数选项,如`--technique`选择注入技术,`--thread`设置并发线程数量,`--sql-shell`启动SQL命令行界面等。 总结,sqlmap作为一款强大的SQL注入工具,能够帮助安全研究人员快速...
1. **GDB简介**: - GDB是GNU调试器,是一个跨平台的调试工具,支持多种编程语言,包括C++。 - 主要功能包括检查程序状态、查找错误、设置断点、查看源代码、管理调用栈等。 - GDB可以在命令行或图形界面下使用,...
在“Java Properties”和“Thread Dump”部分,提供了关于Solr运行时Java属性的详细信息和线程转储的操作方法,这对于性能调优和问题排查非常有用。 “Collection-Specific Tools”和“Core-Specific Tools”部分...
- 在调试多线程程序时,GDB支持多线程调试,通过`info threads`命令查看线程状态,`thread`命令切换线程上下文。 - 当遇到难以复现的错误时,可以通过保存core dump(使用`ulimit -c unlimited`设置),再用GDB加载...
**Thread and Monitor Dump Analyzer (TMDA)** - **适用场景**:崩溃、挂起、性能瓶颈等。 - **输入**:javacore文件。 - **功能**:分析线程和监控器转储,诊断线程问题。 ##### 5. **Thread Analyzer** - **...
#### 一、gdb简介与基本信息操作 gdb(GNU调试器)是GNU项目的一部分,主要用于程序的调试工作。它支持多种操作系统,并能够对C、C++等语言编写的程序进行调试。 ##### 显示gdb版本信息 ```bash gdb --version ``` ...