如何分析线程转储–线程堆栈跟踪

本文介绍了如何分析Java线程堆栈跟踪,包括从下到上的阅读方式,以及如何识别线程状态、执行的任务和挂起条件。通过示例解释了线程转储中的线程执行快照,强调了正确分析线程堆栈跟踪在诊断问题中的重要性。
摘要由CSDN通过智能技术生成
本文是“ 线程转储”分析系列的第5部分。 到目前为止,您已经了解了线程的基本原理以及它们与Java EE容器和JVM的交互。 您还学习了HotSpot和IBM Java VM的不同线程转储格式。 现在是您深入分析过程的时候了。

为了使您能够从线程转储中快速识别问题模式,首先需要了解如何读取线程堆栈跟踪以及如何正确获取“故事”。 这意味着,如果我要您告诉我#38线程在做什么? 您应该能够准确回答; 包括“线程堆栈跟踪”是否显示正常(正常)与挂起状态。

再谈Java堆栈跟踪

你们中的大多数人都熟悉Java堆栈跟踪。 当抛出Java异常时,这是我们从服务器和应用程序日志文件中找到的典型数据。 在这种情况下,Java堆栈跟踪为我们提供了触发Java异常的Thread的代码执行路径,例如java.lang.NoClassDefFoundError,java.lang.NullPpointerException等。此类代码执行路径使我们可以查看不同的层最终导致Java异常的代码。

必须始终从下至上读取Java堆栈跟踪:

  • 底部的行将显示请求的始发者,例如Java / Java EE容器Thread。
  • 堆栈跟踪顶部的第一行将向您显示触发了最后一个Exception的Java类。

让我们通过一个简单的示例来完成此过程。 我们创建了一个示例Java程序,只需执行一些Class方法调用并抛出Exception。 生成的程序输出如下:

JavaStrackTraceSimulator
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

Exception in thread "main" java.lang.IllegalArgumentException:
        at org.ph.javaee.training.td.Class2.call(Class2.java:12)
        at org.ph.javaee.training.td.Class1.call(Class1.java:14)
        at org.ph.javaee.training.td.JavaSTSimulator.main(JavaSTSimulator.java:20)
  • 调用Java程序JavaSTSimulator(通过“主”线程)
  • 然后,模拟器从Class1调用方法call()
  • 然后,Class1方法call()调用Class2方法call()
  • Class2方法call()引发Java异常:java.lang.IllegalArgumentException
  • 然后,在日志/标准输出中显示Java异常

如您所见,导致此异常的代码执行路径始终从下至上显示。

上面的分析过程对于任何Java程序员都应该是众所周知的。 接下来,您将看到线程转储线程堆栈跟踪分析过程与上述Java堆栈跟踪分析非常相似。

线程转储:线程堆栈跟踪分析

从JVM生成的线程转储为您提供了整个JVM进程中所有“创建的”线程的代码级执行快照。 创建线程并不意味着所有这些线程实际上都在做某事。 在从Java EE容器JVM生成的典型线程转储快照中:

  • 一些线程可能正在执行原始计算任务,例如XML解析,IO /磁盘访问等。
  • 一些线程可能正在等待一些阻塞的IO调用,例如远程Web服务调用,DB / JDBC查询等。
  • 那时某些线程可能涉及垃圾回收,例如GC线程
  • 一些线程将等待一些工作要做(不做任何工作的线程通常进入wait()状态)
  • 一些线程可能正在等待其他一些线程完成工作,例如,一些线程正在等待获取某些对象上的监视器锁定(同步块{})

在下一篇文章中,我将返回上面的更多图表,但现在让我们集中讨论堆栈跟踪分析过程。 您的下一个任务是能够尽您所能读取线程堆栈跟踪并了解它在做什么。

线程堆栈跟踪为您提供了其当前执行的快照。 第一行通常包含线程的本机信息,例如其名称,状态,地址等。当前执行堆栈跟踪必须自下而上读取。 请遵循以下分析过程。 您从线程转储分析中获得的经验越多,您就能越快地读取并快速识别每个线程执行的工作:

  • 从底部开始读取线程堆栈跟踪
  • 首先,确定发起者(Java EE容器线程,自定义线程,GC线程,JVM内部线程,独立的Java程序“主”线程等)。
  • 下一步是确定线程正在执行的请求的类型(WebApp,Web Service,JMS,远程EJB(RMI),内部Java EE容器等)。
  • 下一步是从执行堆栈中识别出您所涉及的应用程序模块的形式,例如,线程正在尝试执行的实际核心工作。 分析的复杂性将取决于中间件环境和应用程序的抽象层
  • 下一步是查看第一行之前的最后〜10-20行。 标识线程所涉及的协议或工作,例如HTTP调用,套接字通信,JDBC或原始计算任务,例如磁盘访问,类加载等。
  • 下一步是看第一行。 第一行通常告诉LOT处于Thread状态,因为它是您拍摄快照时执行的当前代码
  • 最后两个步骤的组合将为您提供信息的核心,以总结线程所涉及的工作和/或悬挂条件

现在,使用从JBoss 5生产环境捕获的Thread Dump Thread堆栈跟踪的真实示例,在下面直观地查看上述步骤。 在此示例中,许多线程在创建新的JAX-WS Service实例时都显示了类似的问题,即IO过多。
thread_stack_trace_sample

如您所见,最后10行和第一行将告诉我们线程所涉及的挂起或缓慢状态(如果有)。 底部的几行将为我们提供发起者和请求类型的详细信息。

我希望本文能帮助您了解正确的线程堆栈跟踪分析的重要性。 当我们在以后的文章中介绍最常见的线程转储问题模式时,我将带回更多的线程堆栈跟踪示例。 现在,下一篇文章将教您如何在逻辑孤岛中分解线程转储线程,并提出潜在的根本原因“可疑”列表。

参考: 如何分析线程转储–第5部分:来自JCG合作伙伴 Pierre-Hugues Charbonneau的Java EE支持模式和Java教程博客中的线程堆栈跟踪


翻译自: https://www.javacodegeeks.com/2012/07/how-to-analyze-thread-dump-thread-stack.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值