本文将教大家如何分析JVM线程栈,以及如何从栈信息中找到问题的根源。在我看来,线程堆栈分析技术是JavaEE产品支持工程师必须掌握的技术。线程栈中存储的信息通常远远超出你的想象,我们可以在工作中很好地利用这些信息。我的目标是分享我过去十几年在线程分析方面积累的知识和经验。这些知识和经验是在深入分析各种版本的JVM和各个厂商的JVM供应商中得到的。在这个过程中,我也总结了大量的通用问题模板。那么,准备好了吗,现在就将这篇文章添加为书签,我将在接下来的几周内为您带来这一系列的专题文章。还等什么,赶快把这份线程分析培训计划分享给您的同事朋友吧。听起来不错,我真的应该提高我的线程堆栈分析技能……但是我从哪里开始呢?我的建议是跟随我完成这个线程分析培训计划。以下是我们将在培训中介绍的内容。同时,我会把我处理过的实际案例分享给大家,与大家一起学习和理解。1)线程栈概述及基础知识2)线程栈生成原理及相关工具3)不同JVM线程栈(SunHotSpot、IBMJRE、OracalJRockit)格式差异4)线程栈日志介绍及分析方法5)线程堆栈分析及相关技术6)常见问题模板(线程竞争、死锁、IO调用挂起、垃圾回收/OutOfMemoryError问题、死循环等)7)线程堆栈问题实例分析希望本系列培训能真正帮到你你,所以请继续关注每周的文章更新。但是在学习过程中遇到疑问或者看不懂文章内容怎么办?别担心,就当我是你的导师吧。有什么关于线程栈的问题可以找我咨询(前提是问题不是太low)。请随时选择以下方式与我取得联系:1)直接在本文下方发表评论(不好意思可以匿名)2)将你的线程栈数据提交到根本原因分析论坛3)Email我在@phcharbonneau@hotmail.com可以帮我分析一下我们产品遇到的问题吗?当然,如果你愿意,你可以通过电子邮件或根本原因分析论坛将你的堆栈字段数据发送给我。处理实际问题是学习和提高技能的王道。我真诚地希望您会喜欢这次培训。所以我会尽我所能为大家提供优质的素材,解答大家的各种问题。在介绍线程栈分析技术和问题模型之前,先给大家讲一下基础知识。所以在这篇文章中,我会先介绍最基础的内容,让大家更好的理解JVM、中间件和JavaEE容器之间的交互。JavaVM概述Java虚拟机是JavaEE平台的基础。它是部署和运行中间件和应用程序的地方。JVM为中间件软件和您的Java/JavaEE程序提供以下内容:-(以二进制形式)Java/JavaEE程序执行环境-一些程序功能和工具(IO基础结构、数据结构、线程管理、安全、监控,等等)–动态内存分配和垃圾回收管理你的JVM可以驻留在许多操作系统上(Solaris,AIX,Windows等)并且可以根据你的物理服务器进行配置,你可以在上面安装1到多个JVM进程每个物理/虚拟服务器。JVM和中间件之间的交互??下图显示了JVM、中间件和应用程序之间的高级交互模型。JVM、中间件和应用程序之间的一些简单典型的交互如图所示。如您所见,标准JavaEE应用程序的线程分配是在中间件核心和JVM之间完成的。(当然也有例外,应用程序可以直接调用API创建线程,这种做法并不常见,使用时要特别注意。)同时请注意,有些线程是由JVM内部管理的,典型的一个例子是垃圾收集线程,JVM内部使用它来进行并行垃圾收集处理。由于大多数线程分配是由JavaEE容器完成的,因此能够理解和识别线程堆栈跟踪并能够从线程堆栈数据中识别它对您来说很重要。这使您可以快速了解JavaEE容器正在执行什么类型的请求。从线程转储堆栈分析的角度,您将能够了解从JVM看到的线程池之间的区别并识别请求的类型。最后一节将概述什么是HotSopVM的JVM线程堆栈,以及您将遇到的各种线程。IBMVM线程堆栈格式的详细信息将在第4节中提供给您。请注意,您可以从根本原因分析论坛获取本文的线程堆栈示例。JVM线程栈——它是什么?JVM线程堆栈是给定时间的快照,它为您提供了所有创建的Java线程的完整列表。每个发现的Java线程都会为您提供以下信息:–线程的名称;通常被中间件供应商用来标识线程的ID,通常带有分配的线程池的名称和状态(运行、阻塞等)——线程类型和优先级,例如:daemonprio=3**中间件程序通常创建它们的线程作为守护进程,这意味着这些线程在后台运行;用户提供服务,例如:给你的JavaEE应用**-Java线程ID,例如:tid=0x000000011e52a800**这是通过java.lang.Thread.getId()得到的Java线程ID,常用于增加长整型1..n**实现-nativethreadID,eg:nid=0x251c**,原因是nativethreadID可以让你从操作系统的相关信息,例如大部分CPU使用时间。**–Java线程状态和详细信息,例如:waitingformonitorentry[0xfffffffea5afb000]java.lang.Thread.State:BLOCKED(onobjectmonitor)**可以快速了解线程状态和当前阻塞的可能原因**-Java线程堆栈跟踪;这是迄今为止您可以从线程堆栈中找到的最重要的数据。这这也是您花费最多分析时间的地方,因为Java堆栈跟踪提供了您将在稍后的实践会话中学习的许多类型问题的根本原因所需的90%的信息-Java堆内存分解;从HotSpotVM1.6版本开始,可以在线程栈的末尾看到HotSpot的内存使用情况,比如Java的堆内存(YoungGen、OldGen)&PermGen空间。在分析频繁GC导致的问题时,此信息很有用。您可以使用已知的线程数据或模式来进行快速修复。HeapPSYoungGentotal466944K,used178734K[0xffffffff45c00000,0xffffffff70800000,0xffffffff70800000)edenspace233472K,76%used[0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)fromspace233472K,0%used[0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)tospace233472K,0%used[0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)PSOldGentotal1400832K,used1400831K[0xfffffffef0400000,0xffffffff45c00000,0xffffffff45c00000)objectspace1400832K,99%used[0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)PSPermGentotal262144K,used248475K[0xfffffffed0400000,0xfffffffee0400000,0xfffffffef0400000)objectspace262144K,94%used[0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)线程堆栈信息大拆解为了让大家为了更好地理解,我为您提供了以下图片。在这张图中,对HotSpotVM上的线程栈信息和线程池进行了详细的拆解,如下图所示:从上图可以看出,线程栈是由很多不同的部分组成的。这些信息对于问题分析很重要,但是不同问题模式的分析会用到不同的部分(问题模式将在后面的文章中进行模拟和演示。)现在通过这个分析例子,详细解释一下HoteSpot上线程栈信息的各个组成部分:#Fullthreaddump标识符“Fullthreaddump”是一个全局唯一的关键字,你可以在中间件和单机中使用它在Java版本的线程堆栈信息的输出日志中找到(例如UNIX下使用:kill-3
