JDK14性能管理工具之jstack使用介绍
在之前的文章中,我们介绍了JDK14中jstat工具的使用,本文我们再深入探讨一下jstack工具的使用。
jstack工具主要用来打印java堆栈信息,主要是java的class名字,方法名,字节码索引,行数等信息。
jstack的命令格式
Usage: jstack[-l][-e](toconnecttorunningprocess) Options: -llonglisting.Printsadditionalinformationaboutlocks -eextendedlisting.Printsadditionalinformationaboutthreads -?-h--help-helptoprintthishelpmessage
jstack的参数比较简单,l可以包含锁的信息,e包含了额外的信息。
jstack的使用
我们举个例子:
jstack-l-e53528
输出结果如下:
2020-05-0921:46:51
FullthreaddumpJavaHotSpot(TM)64-BitServerVM(14.0.1+7mixedmode,sharing):
ThreadsclassSMRinfo:
_java_thread_list=0x00007fda0660eb00,length=14,elements={
0x00007fda04811000,0x00007fda05845800,0x00007fda05012000,0x00007fda05847800,
0x00007fda05843800,0x00007fda05854800,0x00007fda0481f000,0x00007fda0481f800,
0x00007fda04018800,0x00007fda041ff800,0x00007fda05a28800,0x00007fda05b1a800,
0x00007fda05b1d800,0x00007fda042be000
}
"ReferenceHandler"#2daemonprio=10os_prio=31cpu=0.67mselapsed=66335.21sallocated=0Bdefined_classes=0tid=0x00007fda04811000nid=0x4603waitingoncondition [0x000070000afe1000]
java.lang.Thread.State:RUNNABLE
atjava.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/NativeMethod)
atjava.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241)
atjava.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)
Lockedownablesynchronizers:
-None
...
"VMThread"os_prio=31cpu=1433.78mselapsed=66335.22stid=0x00007fda0506b000nid=0x4803runnable
"GCThread#0"os_prio=31cpu=18.63mselapsed=66335.23stid=0x00007fda0502a800nid=0x3203runnable
"GCThread#1"os_prio=31cpu=19.64mselapsed=66334.06stid=0x00007fda050e5800nid=0x9d03runnable
"GCThread#2"os_prio=31cpu=17.72mselapsed=66334.06stid=0x00007fda05015000nid=0x6203runnable
"GCThread#3"os_prio=31cpu=14.57mselapsed=66332.78stid=0x00007fda05138800nid=0x6503runnable
"G1MainMarker"os_prio=31cpu=0.25mselapsed=66335.23stid=0x00007fda05031000nid=0x3303runnable
"G1Conc#0"os_prio=31cpu=14.85mselapsed=66335.23stid=0x00007fda05031800nid=0x4b03runnable
"G1Refine#0"os_prio=31cpu=3.25mselapsed=66335.23stid=0x00007fda0583a800nid=0x4a03runnable
"G1YoungRemSetSampling"os_prio=31cpu=5929.79mselapsed=66335.23stid=0x00007fda0505a800nid=0x3503runnable
"VMPeriodicTaskThread"os_prio=31cpu=21862.12mselapsed=66335.13stid=0x00007fda0505b000nid=0xa103waitingoncondition
JNIglobalrefs:43,weakrefs:45
输出的结果我们可以分为下面几个部分:
JVM虚拟机信息
第一部分是JVM虚拟机的信息
2020-05-0921:46:51
FullthreaddumpJavaHotSpot(TM)64-BitServerVM(14.0.1+7mixedmode,sharing):
上面显示了虚拟机的threaddump时间和虚拟机的版本等信息。
ThreadsclassSMRinfo
第二部分是JVM中非JVM(非VM和非GC的线程)的内部线程信息。
ThreadsclassSMRinfo:
_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全称是SafeMemoryReclamation。
什么是SMR呢?简单点讲就是安全的内存分配,一般这个问题会出现在非自动GC的编程语言中如C++。在这些语言中,需要自己来为对象分配内存和销毁对象,这样就可能导致在多线程的环境中,一个地址可能被分配给了多个对象,从而出现了内存分配的不安全。
线程信息
第三部分就是线程的具体信息了:
"ReferenceHandler"#2daemonprio=10os_prio=31cpu=0.67mselapsed=66335.21sallocated=0Bdefined_classes=0tid=0x00007fda04811000nid=0x4603waitingoncondition[0x000070000afe1000] java.lang.Thread.State:RUNNABLE atjava.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/NativeMethod) atjava.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241) atjava.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213) Lockedownablesynchronizers: -None
按照字段的顺序,我们可以把线程信息分为下面几个部分:
- 线程名字:例如ReferenceHandler
- 线程的ID:例如#2
- 是否守护线程:例如daemon,daemonthreads是低优先级的thread,它的作用是为UserThread提供服务。因为daemonthreads的低优先级,并且仅为userthread提供服务,所以当所有的userthread都结束之后,JVM会自动退出,不管是否还有daemonthreads在运行中。
- 优先级:例如prio=10
- OS线程的优先级:例如os_prio=31
- cpu时间:线程获得CPU的时间,例如cpu=0.67ms
- elapsed:线程启动后经过的wallclocktime
- allocated:本线程分配的分配的bytes数
- defined_classes:本线程定义的class个数
注意'allocated='和‘defined_classes='必须要开启-XX:+PrintExtendedThreadInfo才会输出数据。
- Address:java线程的地址,例如:tid=0x00007fda04811000
- OS线程ID:例如nid=0x4603
- 线程状态:例如waitingoncondition
- 最新的Java堆栈指针:最新的java堆栈指针SP,例如:[0x000070000afe1000]
接下来就是线程的堆栈信息:
java.lang.Thread.State:RUNNABLE atjava.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/NativeMethod) atjava.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241) atjava.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)
上面的例子是线程的堆栈信息,并且列出来了线程的状态。
LockedOwnableSynchronizer
接下来的部分是该线程拥有的,可用的用于同步的排它锁对象。
OwnableSynchronizer是一个同步器,这个同步器的同步属性是通过使用AbstractOwnableSynchronizer或者它的子类来实现的。
例如ReentrantLock和ReentrantReadWriteLock中的write-lock(注意不是read-lock,因为需要排它性)就是两个例子。
JVMThreads
接下来是JVM的线程信息,因为这个线程是JVM内部的,所以没有线程ID:
"VMThread"os_prio=31cpu=1433.78mselapsed=66335.22stid=0x00007fda0506b000nid=0x4803runnable
"GCThread#0"os_prio=31cpu=18.63mselapsed=66335.23stid=0x00007fda0502a800nid=0x3203runnable
"GCThread#1"os_prio=31cpu=19.64mselapsed=66334.06stid=0x00007fda050e5800nid=0x9d03runnable
"GCThread#2"os_prio=31cpu=17.72mselapsed=66334.06stid=0x00007fda05015000nid=0x6203runnable
"GCThread#3"os_prio=31cpu=14.57mselapsed=66332.78stid=0x00007fda05138800nid=0x6503runnable
"G1MainMarker"os_prio=31cpu=0.25mselapsed=66335.23stid=0x00007fda05031000nid=0x3303runnable
"G1Conc#0"os_prio=31cpu=14.85mselapsed=66335.23stid=0x00007fda05031800nid=0x4b03runnable
"G1Refine#0"os_prio=31cpu=3.25mselapsed=66335.23stid=0x00007fda0583a800nid=0x4a03runnable
"G1YoungRemSetSampling"os_prio=31cpu=5929.79mselapsed=66335.23stid=0x00007fda0505a800nid=0x3503runnable
"VMPeriodicTaskThread"os_prio=31cpu=21862.12mselapsed=66335.13stid=0x00007fda0505b000nid=0xa103waitingoncondition
JNIReferences
最后一部分是JNI(JavaNativeInterface)引用的信息,注意这些引用可能会导致内存泄露,因为这些native的引用并不会被自动垃圾回收。
JNIglobalrefs:43,weakrefs:45
jstack是分析线程的非常强大的工具,希望大家能够使用起来。
总结
到此这篇关于JDK14性能管理工具之jstack使用介绍的文章就介绍到这了,更多相关JDK14性能管理工具jstack使用内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。