`

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

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

/**
 * 死锁例子
 * @author crane.ding
 * @since 2011-3-20
 */
public class DeadLock {

	public static void main(String[] args) {
		final Object obj_1 = new Object(), obj_2 = new Object();
		
		Thread t1 = new Thread("t1"){
			@Override
			public void run() {
				synchronized (obj_1) {
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {}
					
					synchronized (obj_2) {
						System.out.println("thread t1 done.");
					}
				}
			}
		};
		
		Thread t2 = new Thread("t2"){
			@Override
			public void run() {
				synchronized (obj_2) {
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {}
					
					synchronized (obj_1) {
						System.out.println("thread t2 done.");
					}
				}
			}
		};
		
		t1.start();
		t2.start();
	}
	
}

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

$ jps
  3076 Jps
  448 DeadLock
$ jstack -l 448 > deadlock.jstack

结果文件deadlock.jstack内容如下:
2011-03-20 23:05:20
Full thread dump Java HotSpot(TM) Client VM (19.1-b02 mixed mode, sharing):

"DestroyJavaVM" prio=6 tid=0x00316800 nid=0x9fc waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"t2" prio=6 tid=0x02bcf000 nid=0xc70 waiting for monitor entry [0x02f6f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.demo.DeadLock$2.run(DeadLock.java:40)
	- waiting to lock <0x22a297a8> (a java.lang.Object)
	- locked <0x22a297b0> (a java.lang.Object)

   Locked ownable synchronizers:
	- None

"t1" prio=6 tid=0x02bce400 nid=0xba0 waiting for monitor entry [0x02f1f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.demo.DeadLock$1.run(DeadLock.java:25)
	- waiting to lock <0x22a297b0> (a java.lang.Object)
	- locked <0x22a297a8> (a java.lang.Object)

   Locked ownable synchronizers:
	- None

"Low Memory Detector" daemon prio=6 tid=0x02bb9400 nid=0xa6c runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"CompilerThread0" daemon prio=10 tid=0x02bb2800 nid=0xcb8 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Attach Listener" daemon prio=10 tid=0x02bb1000 nid=0x7f4 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Signal Dispatcher" daemon prio=10 tid=0x02bd2800 nid=0xd80 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Finalizer" daemon prio=8 tid=0x02bab000 nid=0xe1c in Object.wait() [0x02d3f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
	- locked <0x229e1148> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

   Locked ownable synchronizers:
	- None

"Reference Handler" daemon prio=10 tid=0x02ba6800 nid=0xbe0 in Object.wait() [0x02cef000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x229e1048> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:485)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
	- locked <0x229e1048> (a java.lang.ref.Reference$Lock)

   Locked ownable synchronizers:
	- None

"VM Thread" prio=10 tid=0x02b6a400 nid=0x568 runnable 

"VM Periodic Task Thread" prio=10 tid=0x02bc8400 nid=0x75c waiting on condition 

JNI global references: 878


Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x02baaeec (object 0x22a297a8, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x02baa2bc (object 0x22a297b0, a java.lang.Object),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
	at com.demo.DeadLock$2.run(DeadLock.java:40)
	- waiting to lock <0x22a297a8> (a java.lang.Object)
	- locked <0x22a297b0> (a java.lang.Object)
"t1":
	at com.demo.DeadLock$1.run(DeadLock.java:25)
	- waiting to lock <0x22a297b0> (a java.lang.Object)
	- locked <0x22a297a8> (a java.lang.Object)

Found 1 deadlock.

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




4
4
分享到:
评论
3 楼 793059909 2015-01-23  
这种栈信息,可能是什么原因造成的:
3XMTHREADINFO      "Thread-121" J9VMThread:0x000001001F3D7400, j9thread_t:0x000001001894E3C0, java/lang/Thread:0x0700000019B38160, state:CW, prio=5
3XMTHREADINFO1            (native thread ID:0x34E0363, native priority:0x5, native policy:UNKNOWN)
3XMTHREADINFO3           Java callstack:
4XESTACKTRACE                at java/lang/Object.wait(Native Method)
4XESTACKTRACE                at java/lang/Object.wait(Object.java:167)
4XESTACKTRACE                at org/jboss/mx/loading/RepositoryClassLoader.loadClassImpl(RepositoryClassLoader.java:469)
4XESTACKTRACE                at org/jboss/mx/loading/RepositoryClassLoader.loadClass(RepositoryClassLoader.java:393)
4XESTACKTRACE                at java/lang/ClassLoader.loadClass(ClassLoader.java:626)
4XESTACKTRACE                at java/lang/J9VMInternals.verifyImpl(Native Method)
4XESTACKTRACE                at java/lang/J9VMInternals.verify(J9VMInternals.java:72)
4XESTACKTRACE                at java/lang/J9VMInternals.initialize(J9VMInternals.java:134)
2 楼 itzhangyang 2013-06-17  
lz是不是可以说一下怎么解决的groovy并发的问题啊
1 楼 sdh5724 2011-03-21  
$JAVA_HOME/bin 下的几个工具都值得学习使用:
jps
jstat
jstack
jinfo
jmap
.....

这是无工具环境的最后的手段, 可以好好学学使用。 我基本用这些能解决99%的问题哦。

相关推荐

    java诊断与调优常用命令jmap、jstack、jstat使用实战.pdf

    掌握这些命令行工具的使用,能极大地提高对Java应用程序的诊断和优化能力。它们提供了深入洞察应用程序运行状况的能力,使得问题的定位和解决变得更加直接和高效。在面对复杂的生产环境问题时,结合这些工具和适当的...

    实战Java虚拟机——JVM故障诊断与性能优化.pdf

    通过阅读《实战Java虚拟机——JVM故障诊断与性能优化》,读者不仅可以学习到JVM的基础知识,还能掌握如何在实际工作中诊断问题和优化性能,从而提升Java应用程序的运行效率和稳定性。这本书是Java开发者深入理解JVM...

    Java线上故障排查方案.pdf

    3. 终端命令监控(Terminal Command Monitoring):通过执行特定的命令,例如使用jps、jmap、jstack、jinfo、jstat等JDK自带工具,可以获取Java虚拟机(JVM)的运行状态信息。 4. 内存分析工具(Memory Analysis ...

    JDK18-java-se-monitoring-and-management-guide.pdf

    Java SE监控和管理指南提供了详细的指导和best practice,帮助开发者和管理员对Java应用程序进行故障排除。包括使用jcmd和jinfo等工具来诊断和排除故障,使用日志记录和dump文件来分析故障原因等多方面的故障排除...

    实战JAVA虚拟机 JVM故障诊断与性能优化

    《实战JAVA虚拟机 JVM故障诊断与性能优化》这本书深入探讨了Java开发中不可或缺的Java虚拟机(JVM)技术,对于Java开发者来说,理解JVM的...通过深入学习,我们可以更好地驾驭Java虚拟机,提升应用程序的性能和稳定性。

    MPP的jstack分析结果

    它可以帮助开发者查看线程的状态,定位程序的死锁、阻塞等问题,从而辅助诊断和优化Java应用程序的性能。 在MPP环境中,由于系统通常包含大量并行运行的线程,jstack分析显得尤为重要。MPP系统的核心是并行计算,...

    Java虚拟机-jvm故障诊断与性能优化-源码

    - **JMX**:Java管理扩展,允许远程监控和管理应用程序。 5. **JVM故障诊断** - **堆dump分析**:通过jmap生成堆转储文件,使用MAT、VisualVM等工具分析内存泄漏。 - **线程dump**:jstack命令获取线程状态,...

    JDK19-troubleshooting-guide.pdf

    * 使用 Java 的 debug 工具(如 jdb、jconsole 等)来诊断应用程序故障。 * 使用 Java 的性能分析工具(如 VisualVM、Java Mission Control 等)来分析应用程序的性能问题。 * 使用 Java 的日志记录功能来记录...

    JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC 一条龙!.docx

    JAVA 线上故障排查完整套路,从 CPU、磁盘、...我们可以使用各种网络诊断工具来分析网络故障的来源。 本文档提供了一个完整的 Java 线上故障排查套路,涵盖了 CPU、磁盘、内存、网络和 GC 等多个方面的故障排查方法。

    Linux下启动JAVA

    如果Java应用程序被打包成了一个JAR(Java Archive)文件,可以使用`java -jar`命令来运行: ```bash java -jar myapp.jar ``` 6. **配置JVM参数** 在启动Java应用程序时,可能需要调整Java虚拟机(JVM)的...

    Java应用系统的复杂网络分析.zip

    当Java应用出现网络问题时,可以利用Java的内置工具如jstack、jmap、jconsole等进行诊断,或者使用第三方工具如Wireshark抓包分析网络流量,找出问题根源。此外,日志记录和异常处理机制也是必不可少的,它们可以...

    java JDK帮助文档

    6. **Java性能分析器** (jmap, jhat, jstack, jinfo):这些工具用于诊断和优化Java应用的内存使用、线程状态和配置信息。 7. **Java Mission Control** (JMC):一套高级的性能分析和故障排查工具,适用于复杂的生产...

    Java诊断工具源代码.zip

    本压缩包“Java诊断工具源代码.zip”包含了用于深入理解并优化Java应用程序的相关工具源代码,这对于学习和实践Java性能调优至关重要。下面我们将详细探讨其中涉及的一些关键知识点。 1. **JVM内置工具**:Java...

    java自带的工具Jstack截取进程中的堆栈信息

    总之,Jstack是JDK提供的一个简单、强大的工具,可以有效地帮助开发者和运维人员进行故障定位和性能监控,是进行Java应用程序日常维护不可或缺的一部分。掌握Jstack的使用方法,对于解决Java应用中的线程问题、提高...

    Java线上故障排查方案(2).pdf

    Arthas是一个Java诊断工具,其提供了丰富的命令用于对Java应用进行问题诊断。比如,可以使用dashboard命令查看应用的实时性能数据,或者使用thread命令查看线程状态和堆栈信息。 JVM问题定位同样重要,它涉及到具体...

    Troubleshooting Guide for Java

    Native Memory Tracking允许开发者跟踪Java应用程序中的本机内存使用情况。这对于分析由于本机代码或库导致的内存泄漏等问题特别有用。 ##### 启用方式 1. **设置环境变量**:通过设置`_JAVA_OPTIONS`环境变量来...

    tda看ThreadDump文件

    在Java应用程序的运行过程中,有时候会遇到性能问题或者线程阻塞的情况,这时开发者需要深入分析应用程序的内部状态,特别是线程的状态。`jstack`是Java标准工具集中的一个命令行工具,它能用于生成Java虚拟机当前...

    JDK监控和故障处理工具

    在Java开发和运行环境中,监控和故障处理是确保应用程序稳定运行的关键环节。本篇文章将详细介绍Java开发工具包(JDK)中的一些重要监控和故障处理工具,这些工具可以帮助开发者识别和解决生产环境中的内存溢出问题...

    Java工程师应用技术汇总

    - **HouseMD**:故障诊断工具,可以收集各种信息帮助诊断问题。 - **jmxterm**:基于终端的JMX客户端。 - **TBJMap**:分析JVM堆转储文件的工具。 **1.1.4 Java诊断工具** - **Eclipse Memory Analyzer (MAT)**:...

Global site tag (gtag.js) - Google Analytics