JDK14性能管理工具之jstack使用介绍

作者:flydean 时间:2022-10-11 18:48:01 

在之前的文章中,我们介绍了JDK14中jstat工具的使用,本文我们再深入探讨一下jstack工具的使用。

jstack工具主要用来打印java堆栈信息,主要是java的class名字,方法名,字节码索引,行数等信息。

jstack的命令格式


Usage:
 jstack [-l][-e] <pid>
   (to connect to running process)

Options:
 -l long listing. Prints additional information about locks
 -e extended listing. Prints additional information about threads
 -? -h --help -help to print this help message

jstack的参数比较简单,l可以包含锁的信息,e包含了额外的信息。

jstack的使用

我们举个例子:

jstack -l -e 53528

输出结果如下:

2020-05-09 21:46:51
Full thread dump Java HotSpot(TM) 64-Bit Server VM (14.0.1+7 mixed mode, sharing):
Threads class SMR info:
_java_thread_list=0x00007fda0660eb00, length=14, elements={
0x00007fda04811000, 0x00007fda05845800, 0x00007fda05012000, 0x00007fda05847800,
0x00007fda05843800, 0x00007fda05854800, 0x00007fda0481f000, 0x00007fda0481f800,
0x00007fda04018800, 0x00007fda041ff800, 0x00007fda05a28800, 0x00007fda05b1a800,
0x00007fda05b1d800, 0x00007fda042be000
}
"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.67ms elapsed=66335.21s allocated=0B defined_classes=0 tid=0x00007fda04811000 nid=0x4603 waiting on condition  [0x000070000afe1000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/Native Method)
    at java.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241)
    at java.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)
   Locked ownable synchronizers:
    - None
...
"VM Thread" os_prio=31 cpu=1433.78ms elapsed=66335.22s tid=0x00007fda0506b000 nid=0x4803 runnable
"GC Thread#0" os_prio=31 cpu=18.63ms elapsed=66335.23s tid=0x00007fda0502a800 nid=0x3203 runnable
"GC Thread#1" os_prio=31 cpu=19.64ms elapsed=66334.06s tid=0x00007fda050e5800 nid=0x9d03 runnable
"GC Thread#2" os_prio=31 cpu=17.72ms elapsed=66334.06s tid=0x00007fda05015000 nid=0x6203 runnable
"GC Thread#3" os_prio=31 cpu=14.57ms elapsed=66332.78s tid=0x00007fda05138800 nid=0x6503 runnable
"G1 Main Marker" os_prio=31 cpu=0.25ms elapsed=66335.23s tid=0x00007fda05031000 nid=0x3303 runnable
"G1 Conc#0" os_prio=31 cpu=14.85ms elapsed=66335.23s tid=0x00007fda05031800 nid=0x4b03 runnable
"G1 Refine#0" os_prio=31 cpu=3.25ms elapsed=66335.23s tid=0x00007fda0583a800 nid=0x4a03 runnable
"G1 Young RemSet Sampling" os_prio=31 cpu=5929.79ms elapsed=66335.23s tid=0x00007fda0505a800 nid=0x3503 runnable
"VM Periodic Task Thread" os_prio=31 cpu=21862.12ms elapsed=66335.13s tid=0x00007fda0505b000 nid=0xa103 waiting on condition
JNI global refs: 43, weak refs: 45

输出的结果我们可以分为下面几个部分:

JVM虚拟机信息

第一部分是JVM虚拟机的信息

2020-05-09 21:46:51
Full thread dump Java HotSpot(TM) 64-Bit Server VM (14.0.1+7 mixed mode, sharing):

上面显示了虚拟机的thread dump时间和虚拟机的版本等信息。

Threads class SMR info

第二部分是JVM中非JVM(非VM和非GC的线程)的内部线程信息。

Threads class SMR info:
_java_thread_list=0x00007fda0660eb00, length=14, elements={
0x00007fda04811000, 0x00007fda05845800, 0x00007fda05012000, 0x00007fda05847800,
0x00007fda05843800, 0x00007fda05854800, 0x00007fda0481f000, 0x00007fda0481f800,
0x00007fda04018800, 0x00007fda041ff800, 0x00007fda05a28800, 0x00007fda05b1a800,
0x00007fda05b1d800, 0x00007fda042be000
}

这些elements是和后面线程的tid相匹配的。表示的是本地线程对象的地址,注意这些不是线程的ID。

大家可能注意到了里面写的是SMR, SMR全称是Safe Memory Reclamation。

什么是SMR呢?简单点讲就是安全的内存分配,一般这个问题会出现在非自动GC的编程语言中如C++。在这些语言中,需要自己来为对象分配内存和销毁对象,这样就可能导致在多线程的环境中,一个地址可能被分配给了多个对象,从而出现了内存分配的不安全。

线程信息

第三部分就是线程的具体信息了:


"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.67ms elapsed=66335.21s allocated=0B defined_classes=0 tid=0x00007fda04811000 nid=0x4603 waiting on condition [0x000070000afe1000]
 java.lang.Thread.State: RUNNABLE
 at java.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/Native Method)
 at java.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241)
 at java.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)

Locked ownable synchronizers:
 - None

按照字段的顺序,我们可以把线程信息分为下面几个部分:

  • 线程名字:例如Reference Handler

  • 线程的ID:例如#2

  • 是否守护线程:例如daemon,daemon threads是低优先级的thread,它的作用是为User Thread提供服务。 因为daemon threads的低优先级,并且仅为user thread提供服务,所以当所有的user thread都结束之后,JVM会自动退出,不管是否还有daemon threads在运行中。

  • 优先级:例如prio=10

  • OS线程的优先级:例如os_prio=31

  • cpu时间:线程获得CPU的时间,例如cpu=0.67ms

  • elapsed:线程启动后经过的wall clock time

  • allocated:本线程分配的分配的bytes数

  • defined_classes:本线程定义的class个数

注意'allocated=' 和 ‘defined_classes=' 必须要开启 -XX:+PrintExtendedThreadInfo才会输出数据。

  • Address:java线程的地址,例如:tid=0x00007fda04811000

  • OS线程ID:例如nid=0x4603

  • 线程状态:例如waiting on condition

  • 最新的Java堆栈指针:最新的java堆栈指针SP,例如:[0x000070000afe1000]

接下来就是线程的堆栈信息:


java.lang.Thread.State: RUNNABLE
 at java.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/Native Method)
 at java.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241)
 at java.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)

上面的例子是线程的堆栈信息,并且列出来了线程的状态。

Locked Ownable Synchronizer

接下来的部分是该线程拥有的,可用的用于同步的排它锁对象。

Ownable Synchronizer是一个同步器,这个同步器的同步属性是通过使用AbstractOwnableSynchronizer或者它的子类来实现的。

例如ReentrantLock和ReentrantReadWriteLock中的write-lock(注意不是read-lock,因为需要排它性)就是两个例子。

JVM Threads

接下来是JVM的线程信息,因为这个线程是JVM内部的,所以没有线程ID:

"VM Thread" os_prio=31 cpu=1433.78ms elapsed=66335.22s tid=0x00007fda0506b000 nid=0x4803 runnable

"GC Thread#0" os_prio=31 cpu=18.63ms elapsed=66335.23s tid=0x00007fda0502a800 nid=0x3203 runnable

"GC Thread#1" os_prio=31 cpu=19.64ms elapsed=66334.06s tid=0x00007fda050e5800 nid=0x9d03 runnable

"GC Thread#2" os_prio=31 cpu=17.72ms elapsed=66334.06s tid=0x00007fda05015000 nid=0x6203 runnable

"GC Thread#3" os_prio=31 cpu=14.57ms elapsed=66332.78s tid=0x00007fda05138800 nid=0x6503 runnable

"G1 Main Marker" os_prio=31 cpu=0.25ms elapsed=66335.23s tid=0x00007fda05031000 nid=0x3303 runnable

"G1 Conc#0" os_prio=31 cpu=14.85ms elapsed=66335.23s tid=0x00007fda05031800 nid=0x4b03 runnable

"G1 Refine#0" os_prio=31 cpu=3.25ms elapsed=66335.23s tid=0x00007fda0583a800 nid=0x4a03 runnable

"G1 Young RemSet Sampling" os_prio=31 cpu=5929.79ms elapsed=66335.23s tid=0x00007fda0505a800 nid=0x3503 runnable
"VM Periodic Task Thread" os_prio=31 cpu=21862.12ms elapsed=66335.13s tid=0x00007fda0505b000 nid=0xa103 waiting on condition

JNI References

最后一部分是JNI(Java Native Interface)引用的信息,注意这些引用可能会导致内存泄露,因为这些native的引用并不会被自动垃圾回收。

JNI global refs: 43, weak refs: 45

jstack是分析线程的非常强大的工具,希望大家能够使用起来。

来源:http://www.flydean.com/jdk14-jvm-jstack/

标签:jdk14,性能管理工具,jstack
0
投稿

猜你喜欢

  • IDEA 2020.1 搜索不到Chinese ​(Simplified)​ Language Pack EAP,无法安装的问题

    2023-11-10 23:54:01
  • springboot返回值转成JSONString的处理方式

    2022-09-27 12:04:46
  • Java数组的基本学习教程

    2021-07-14 05:08:00
  • Java 数据结构与算法系列精讲之哈希算法实现

    2022-01-10 23:56:07
  • Java8之lambda最佳实践_动力节点Java学院整理

    2023-11-28 00:07:28
  • Java多态和实现接口的类的对象赋值给接口引用的方法(推荐)

    2023-11-26 11:59:41
  • c# List find()方法返回值的问题说明(返回结果为对象的指针)

    2023-11-20 21:55:34
  • c#实现16进制和字符串之间转换的代码

    2023-07-22 08:28:09
  • jdk8使用stream实现两个list集合合并成一个(对象属性的合并)

    2023-08-05 16:49:30
  • C# 委托的三种调用示例(同步调用 异步调用 异步回调)

    2023-06-09 10:29:56
  • java Semaphore共享锁实现原理解析

    2021-11-02 23:12:38
  • Java日常练习题,每天进步一点点(61)

    2021-07-17 06:56:13
  • Spring之spring-context-indexer依赖详解

    2023-11-23 12:21:41
  • Java基于解释器模式实现定义一种简单的语言功能示例

    2021-06-18 15:53:42
  • Spring创建bean实例的几种方式分享

    2022-02-21 22:08:19
  • 亲手教你SpringBoot中的多数据源集成问题

    2023-08-19 02:57:20
  • Java中synchronized正确使用方法解析

    2021-12-20 13:00:39
  • C#数据结构之堆栈(Stack)实例详解

    2022-12-17 21:25:37
  • 浅谈android Fragment横竖屏翻转对重新加载的要求

    2023-07-27 21:55:28
  • Java中Request请求转发详解

    2021-05-25 20:53:42
  • asp之家 软件编程 m.aspxhome.com