最近一段时间,我们的生产系统升级频繁出现故障,具体故障现象是启动后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造成的,同时也记录了线程的堆栈和代码行数,通过这个堆栈和行数我们就可以去检查对应的代码块,从而发现问题和解决问题。
相关推荐
掌握这些命令行工具的使用,能极大地提高对Java应用程序的诊断和优化能力。它们提供了深入洞察应用程序运行状况的能力,使得问题的定位和解决变得更加直接和高效。在面对复杂的生产环境问题时,结合这些工具和适当的...
Java SE监控和管理指南提供了详细的指导和best practice,帮助开发者和管理员对Java应用程序进行故障排除。包括使用jcmd和jinfo等工具来诊断和排除故障,使用日志记录和dump文件来分析故障原因等多方面的故障排除...
3. 终端命令监控(Terminal Command Monitoring):通过执行特定的命令,例如使用jps、jmap、jstack、jinfo、jstat等JDK自带工具,可以获取Java虚拟机(JVM)的运行状态信息。 4. 内存分析工具(Memory Analysis ...
通过阅读《实战Java虚拟机——JVM故障诊断与性能优化》,读者不仅可以学习到JVM的基础知识,还能掌握如何在实际工作中诊断问题和优化性能,从而提升Java应用程序的运行效率和稳定性。这本书是Java开发者深入理解JVM...
《实战JAVA虚拟机 JVM故障诊断与性能优化》这本书深入探讨了Java开发中不可或缺的Java虚拟机(JVM)技术,对于Java开发者来说,理解JVM的...通过深入学习,我们可以更好地驾驭Java虚拟机,提升应用程序的性能和稳定性。
- **JMX**:Java管理扩展,允许远程监控和管理应用程序。 5. **JVM故障诊断** - **堆dump分析**:通过jmap生成堆转储文件,使用MAT、VisualVM等工具分析内存泄漏。 - **线程dump**:jstack命令获取线程状态,...
它可以帮助开发者查看线程的状态,定位程序的死锁、阻塞等问题,从而辅助诊断和优化Java应用程序的性能。 在MPP环境中,由于系统通常包含大量并行运行的线程,jstack分析显得尤为重要。MPP系统的核心是并行计算,...
* 使用 Java 的 debug 工具(如 jdb、jconsole 等)来诊断应用程序故障。 * 使用 Java 的性能分析工具(如 VisualVM、Java Mission Control 等)来分析应用程序的性能问题。 * 使用 Java 的日志记录功能来记录...
JAVA 线上故障排查完整套路,从 CPU、磁盘、...我们可以使用各种网络诊断工具来分析网络故障的来源。 本文档提供了一个完整的 Java 线上故障排查套路,涵盖了 CPU、磁盘、内存、网络和 GC 等多个方面的故障排查方法。
当Java应用出现网络问题时,可以利用Java的内置工具如jstack、jmap、jconsole等进行诊断,或者使用第三方工具如Wireshark抓包分析网络流量,找出问题根源。此外,日志记录和异常处理机制也是必不可少的,它们可以...
如果Java应用程序被打包成了一个JAR(Java Archive)文件,可以使用`java -jar`命令来运行: ```bash java -jar myapp.jar ``` 6. **配置JVM参数** 在启动Java应用程序时,可能需要调整Java虚拟机(JVM)的...
6. **Java性能分析器** (jmap, jhat, jstack, jinfo):这些工具用于诊断和优化Java应用的内存使用、线程状态和配置信息。 7. **Java Mission Control** (JMC):一套高级的性能分析和故障排查工具,适用于复杂的生产...
总之,Jstack是JDK提供的一个简单、强大的工具,可以有效地帮助开发者和运维人员进行故障定位和性能监控,是进行Java应用程序日常维护不可或缺的一部分。掌握Jstack的使用方法,对于解决Java应用中的线程问题、提高...
本压缩包“Java诊断工具源代码.zip”包含了用于深入理解并优化Java应用程序的相关工具源代码,这对于学习和实践Java性能调优至关重要。下面我们将详细探讨其中涉及的一些关键知识点。 1. **JVM内置工具**:Java...
Native Memory Tracking允许开发者跟踪Java应用程序中的本机内存使用情况。这对于分析由于本机代码或库导致的内存泄漏等问题特别有用。 ##### 启用方式 1. **设置环境变量**:通过设置`_JAVA_OPTIONS`环境变量来...
Arthas是一个Java诊断工具,其提供了丰富的命令用于对Java应用进行问题诊断。比如,可以使用dashboard命令查看应用的实时性能数据,或者使用thread命令查看线程状态和堆栈信息。 JVM问题定位同样重要,它涉及到具体...
- **功能**:`jstack`主要用于诊断Java应用的线程堆栈信息,它能够显示每个线程的详细信息,包括线程ID、线程状态、锁持有的对象、在哪个方法中挂起等。 - **使用方法**:通过命令行输入`jstack <pid>`,其中`pid`...
在Java开发和运行环境中,监控和故障处理是确保应用程序稳定运行的关键环节。本篇文章将详细介绍Java开发工具包(JDK)中的一些重要监控和故障处理工具,这些工具可以帮助开发者识别和解决生产环境中的内存溢出问题...
- **HouseMD**:故障诊断工具,可以收集各种信息帮助诊断问题。 - **jmxterm**:基于终端的JMX客户端。 - **TBJMap**:分析JVM堆转储文件的工具。 **1.1.4 Java诊断工具** - **Eclipse Memory Analyzer (MAT)**:...