JVM Thread Dump 文件分析

Thread Dump介绍Thread Dump是非常有用的诊断JAVA应用问题的工具 。每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-dump的能力,虽然各个 Java虚拟机打印的thread dump略有不同,但是大多都提供了每个线程的所有信息,例如: 线程状态、线程 Id、本机 Id、线程名称、堆栈跟踪、优先级 。
Thread Dump特点

  1. 能在各种操作系统下使用
  2. 能在各种Java应用服务器下使用
  3. 可以在生产环境下使用而不影响系统的性能
  4. 可以将问题直接定位到应用程序的代码行上(对于线上排查问题非常有用)
它能帮我们解决哪些线上问题?Thread dump 能帮我们定位到 例如 CPU 峰值、应用程序中的无响应性、响应时间差、线程挂起、高内存消耗 。
如何抓取Thread Dump一般当服务器挂起,崩溃或者性能底下时,就需要抓取服务器的线程堆栈(Thread Dump)用于后续的分析. 在实际运行中,往往一次 dump的信息,还不足以确认问题 。为了反映线程状态的动态变化,需要接连多次做threaddump,每次间隔10-20s,建议至少产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性 。
获取thread dump
JDK自带命令行工具获取PID,再获取ThreadDump:1. jps 或 ps –ef|grep java (获取PID)2. jstack [-l ]<pid> | tee -a jstack.log(获取ThreadDump)实操演练获取所有线程的thread dump 分两步.
  • 第一步 获取进程的PID
    使用Jps 获取所有java进程的信息

JVM Thread Dump 文件分析

文章插图
  • 第二步 选取对应的pid 例如上图红框中的数字串 使用Jstack获取所有线程栈信息
jstack-l9468 | tee -a jstack.log
JVM Thread Dump 文件分析

文章插图
日志字段分析我们把Thread dump文件分为2个部分来理解
拿我们的例子来说:
//头部信息包含 当前时间jvm信息2021-01-14 17:00:51Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode)://线程info信息块"ajp-nio-8019-exec-7" #75 daemon prio=5 os_prio=0 tid=0x00007fa0cc37e800 nid=0x2af3 waiting on condition [0x00007fa02eceb000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for<0x00000000f183aa30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)at org.Apache.Tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at org.apache.tomcat.util.threads.TaskThread$WrAppingRunnable.run(TaskThread.java:61)at java.lang.Thread.run(Thread.java:748)线程info信息块各个参数的意义:
  • 线程名称:ajp-nio-8019-exec-7
  • 线程类型:daemon
  • 优先级: 默认是5
  • jvm线程id:tid=0x00007fa0cc37e800,jvm内部线程的唯一标识(通过java.lang.Thread.getId()获取,通常用自增方式实现 。)
  • 对应系统线程id(NativeThread ID):nid=0x2af3,和top命令查看的线程pid对应,不过一个是10进制,一个是16进制 。(通过命令:top -H -p pid,可以查看该进程的所有线程信息)
  • 线程状态:java.lang.Thread.State: WAITING (parking)
  • 线程调用栈信息:用于代码的分析 。堆栈信息应该从下向上解读,因为程序调用的顺序是从下向上的 。
系统线程状态 (Native Thread Status)系统线程有如下状态: