如何分析线程堆栈

如题所述

  JVM线程堆栈是一个给定时间的快照,它能向你提供所有被创建出来的Java线程的完整清单.

  每一个被发现的Java线程都会给你如下信息:

  – 线程的名称;经常被中间件厂商用来识别线程的标识,一般还会带上被分配的线程池名称以及状态 (运行,阻塞等等.)

  – 线程类型 & 优先级,例如 : daemon prio=3 ** 中间件程序一般以后台守护的形式创建他们的线程,这意味着这些线程是在后台运行的;它们会向它们的用户提供服务,例如:向你的Java EE应用程序 **

  – Java线程ID,例如 : tid=0x000000011e52a800 ** 这是通过 java.lang.Thread.getId() 获得的Java线程ID,它常常用自增长的长整形 1..n** 实现

  – 原生线程ID,例如 : nid=0x251c** ,之所以关键是因为原生线程ID可以让你获得诸如从操作系统的角度来看那个线程在你的JVM中使用了大部分的CPU时间等这样的相关信息. **

  – Java线程状态和详细信息,例如: waiting for monitor entry [0xfffffffea5afb000] java.lang.Thread.State: BLOCKED (on object monitor)
  ** 可以快速的了解到线程状态极其当前阻塞的可能原因 **

  – Java线程栈跟踪;这是目前为止你能从线程堆栈中找到的最重要的数据. 这也是你花费最多分析时间的地方,因为Java栈跟踪向提供了你将会在稍后的练习环节了解到的导致诸多类型的问题的根本原因,所需要的90%的信息。

  – Java 堆内存分解; 从HotSpot VM 1.6版本开始,在线程堆栈的末尾处可以看到HotSpot的内存使用情况,比如说Java的堆内存(YoungGen, OldGen) & PermGen 空间。这个信息对分析由于频繁GC而引起的问题时,是很有用的。你可以使用已知的线程数据或模式做一个快速的定位。

  Heap
  PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
  eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
  from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
  to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
  PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
  object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
  PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
  object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)
  线程堆栈信息大拆解

  为了让大家更好的理解,给大家提供了下面的这张图,在这张图中将HotSpot VM上的线程堆栈信息和线程池做了详细的拆解,如下图所示:

  上图中可以看出线程堆栈是由多个不同部分组成的。这些信息对问题分析都很重要,但对不同的问题模式的分析会使用不同的部分(问题模式会在后面的文章中做模拟和演示。)

  现在通过这个分析样例,给大家详细解释一下HoteSpot上线程堆栈信息中的各个组成部分:

  # Full thread dump标示符

  “Full thread dump”是一个全局唯一的关键字,你可以在中间件和单机版本Java的线程堆栈信息的输出日志中找到它(比如说在UNIX下使用:kill -3 <PID> )。这是线程堆栈快照的开始部分。

  Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.0-b11 mixed mode):
  # Java EE 中间件,第三方以及自定义应用软件中的线程

  这个部分是整个线程堆栈的核心部分,也是通常需要花费最多分析时间的部分。堆栈中线程的个数取决你使用的中间件,第三方库(可能会有独立线程)以及你的应用程序(如果创建自定义线程,这通常不是一个很好的实践)。

  在我们的示例线程堆栈中,WebLogic是我们所使用的中间件。从Weblogic 9.2开始, 会使用一个用“’weblogic.kernel.Default (self-tuning)”唯一标识的能自行管理的线程池

  "[STANDBY] ExecuteThread: '414' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=3 tid=0x000000010916a800 nid=0x2613 in Object.wait() [0xfffffffe9edff000]
  java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0xffffffff27d44de0> (a weblogic.work.ExecuteThread)
  at java.lang.Object.wait(Object.java:485)
  at weblogic.work.ExecuteThread.waitForRequest(ExecuteThread.java:160)
  - locked <0xffffffff27d44de0> (a weblogic.work.ExecuteThread)
  at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
  # HotSpot VM 线程

  这是一个有Hotspot VM管理的内部线程,用于执行内部的原生操作。一般你不用对此操太多心,除非你(通过相关的线程堆栈以及 prstat或者原生线程Id)发现很高的CPU占用率.

  "VM Periodic Task Thread" prio=3 tid=0x0000000101238800 nid=0x19 waiting on condition
  # HotSpot GC 线程

  当使用 HotSpot 进行并行 GC (如今在使用多个物理核心的环境下很常见), 默认创建的HotSpot VM 或者每个JVM管理一个有特定标识的GC线程时. 这些GC线程可以让VM以并行的方式执行其周期性的GC清理, 这会导致GC时间的总体减少;与此同时的代价是CPU的使用时间会增加.

  "GC task thread#0 (ParallelGC)" prio=3 tid=0x0000000100120000 nid=0x3 runnable
  "GC task thread#1 (ParallelGC)" prio=3 tid=0x0000000100131000 nid=0x4 runnable
  ………………………………………………………………………………………………………………………………………………………………
  这事非常关键的数据,因为当你遇到跟GC有关的问题,诸如过度GC、内存泄露等问题是,你将可以利用这些线程的原生Id值关联的操作系统或者Java线程,进而发现任何对CPI时间的高占用. 未来的文章你将会了解到如何识别并诊断这样的问题.

  # JNI 全局引用计数

  JNI (Java 本地接口)的全局引用就是从本地代码到由Java垃圾收集器管理的Java对象的基本的对象引用. 它的角色就是阻止对仍然在被本地代码使用,但是技术上已经不是Java代码中的“活动的”引用了的对象的垃圾收集.

  同时为了侦测JNI相关的泄露而留意JNI引用也很重要. 如果你的程序直接使用了JNI,或者像监听器这样的第三方工具,就容易造成本地的内存泄露.

  JNI global references: 1925
  # Java 堆栈使用视图

  这些数据被添加回了 JDK 1 .6 ,向你提供有关Hotspot堆栈的一个简短而快速的视图. 我发现它在当我处理带有过高CPU占用的GC相关的问题时非常有用,你可以在一个单独的快照中同时看到线程堆栈以及Java堆的信息,让你当时就可以在一个特定的Java堆内存空间中解析(或者排除)出任何的关键点. 你如在我们的示例线程堆栈中所见,Java 的堆 OldGen 超出了最大值!

  Heap
  PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
  eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
  from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
  to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
  PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
  object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
  PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
  object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)
  我希望这篇文章能对你理解Hotspot VM线程堆栈的基本信息有所帮助。
温馨提示:内容为网友见解,仅供参考
无其他回答

如何分析线程堆栈
– Java 堆内存分解; 从HotSpot VM 1.6版本开始,在线程堆栈的末尾处可以看到HotSpot的内存使用情况,比如说Java的堆内存(YoungGen, OldGen) & PermGen 空间。这个信息对分析由于频繁GC而引起的问题时,是很有用的。你可以使用已知的线程数据或模式做一个快速的定位。Heap PSYoungGen total 466944K,...

如何分析线程堆栈
一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进...

请问线程堆栈是什么意思?能够简单解释下吗?
线程是进程中的一个最小单位。堆是自己分配的空间,需要自主释放。栈是系统自动分配的空间。

java中什么是堆和栈,如何应用,最好举个例子,并详细地说明一下,谢谢了...
Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行...

一篇详解什么是线程dump文件,我们又该如何分析?
ThreadMXBean:用于编程方式捕获线程转储,尤其在死锁检测上。手动分析线程转储分析有助于解决多线程问题,如死锁、锁争用,通过查看堆栈跟踪定位问题。通过一步步解读转储,找出占用CPU过多或处于阻塞状态的线程。工具辅助除了手动,还有在线和离线工具,如DevOps偏爱的FastThread、开源的Spotify和Jstack.review...

如何使用jstack分析线程状态
在thread dump中每个线程都有一个nid,找到对应的nid即可;隔段时间再执行一次stack命令获取thread dump,区分两份dump是否有差别,在nid=0x246c的线程调用栈中,发现该线程一直在执行JstackCase类第33行的calculate方法,得到这个信息,就可以检查对应的代码是否有问题。通过thread dump分析线程状态 ...

巧用jstack定位性能问题
通过使用Jstack工具,可以获取应用运行时的线程堆栈,方便我们发现和定位隐秘的性能问题。常见的性能问题,如线程的运行状态、数据库连接池不够用导致响应时间久、线程阻塞导致响应变慢、系统CPU占用率高等,都可以通过线程堆栈来解决。文章通过具体实例展示了如何利用Jstack工具分析和解决这些问题。当Tomcat应用...

什么是栈和堆
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据在多个线程或者多个栈之间是不可以共享的...

jstack 命令的使用和问题排查分析思路
jstack的使用和分析思路在使用jstack时,需理解Java线程的六种状态,并关注Dump文件中的关键状态,如活跃、等待或阻塞等。实战操作中,首先通过top命令检查进程CPU使用情况,如top -Hp pid,找出占用率高的线程,如pid为21350。接着,使用jstack 21350命令查看其堆栈信息,并将结果输出到文件。线程堆栈中...

JVM性能调优命令之jstack
jstack是Java虚拟机自带的线程堆栈跟踪工具,用于统计和分析线程状态。要定位CPU高占用问题,首先使用top命令查看Java进程的实时CPU使用情况,进一步通过ps aux | grep PID确认问题进程。接着,使用ps -mp pid -o THREAD,tid,time找出耗时最高的线程ID。将线程ID转换为16进制格式,然后使用jstack pid |...

相似回答