文章来源:https://blog.csdn.net/wufaliang003/article/details/80414267java
jstack是java虚拟机自带的一种堆栈跟踪工具。c++
jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的缘由,多线程
如线程间死锁、死循环、请求外部资源致使的长时间等待等。 线程出现停顿的时候经过jstack来查看各个线程的调用堆栈,就能够知道没有响应的线程到底在后台作什么事情,或者框架
等待什么资源。 若是java程序崩溃生成core文件,jstack工具能够用来得到core文件的java stack和native stack的信息,从而能够轻松地知道java程序是如何崩溃和在程工具
序何处发生问题。另外,jstack工具还能够附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 若是如今运行的java程序呈现hungui
的状态,jstack是很是有用的。this
jstack命令:spa
Usage: jstack [-l] <pid> (to connect to running process) jstack -F [-m] [-l] <pid> (to connect to a hung process) jstack [-m] [-l] <executable> <core> (to connect to a core file) jstack [-m] [-l] [server_id@]<remote server IP or hostname> (to connect to a remote debug server) Options: -F to force a thread dump. Use when jstack <pid> does not respond (process is hung) -m to print both java and native frames (mixed mode) -l long listing. Prints additional information about locks -h or -help to print this help message
-F 当’jstack [-l] pid’没有相应的时候强制打印栈信息,若是直接jstack无响应时,用于强制jstack,通常状况不须要使用.net
-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表,会使得JVM停顿得长久得多线程
(可能会差不少倍,好比普通的jstack可能几毫秒和一次GC没区别,加了-l 就是近一秒的时间),-l 建议不要用。通常状况不须要使用
-m 打印java和native c/c++ 框架的全部栈信息.能够打印JVM的堆栈,显示上Native的栈帧,通常应用排查不须要使用
执行命令:
jstack -m 12905
Attaching to process ID 12905, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01 Deadlock Detection: No deadlocks found. ----------------- 12908 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad07875a5 Unsafe_Park + 0x125
0x00007fcacc4b17f8 * sun.misc.Unsafe.park(boolean, long) bci:0 (Interpreted frame) 0x00007fcacc4a5058 * java.util.concurrent.locks.LockSupport.park(java.lang.Object) bci:14 line:186 (Interpreted frame) 0x00007fcacc4a5058 * java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt() bci:1 line:834 (Interpreted frame) 0x00007fcacc4a5350 * java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(int) bci:72 line:994 (Interpreted frame) 0x00007fcacc4a5058 * java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(int) bci:24 line:1303 (Interpreted frame)
想要经过jstack命令来分析线程的状况的话,首先要知道线程都有哪些状态,下面这些状态是咱们使用jstack命令查看线程堆栈信息时可能会看到的线程的几种状态:
NEW,未启动的。不会出如今Dump中。
RUNNABLE,在虚拟机内执行的。
BLOCKED,受阻塞并等待监视器锁。
WATING,无限期等待另外一个线程执行特定操做。
TIMED_WATING,有时限的等待另外一个线程的特定操做。
TERMINATED,已退出的。
在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 Monitor是 Java中用以实现线程之间的互斥与协做的主要手段,它能够当作是对象或者 Class的锁。每个对象都有,
也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图:
进入区(Entrt Set):表示线程经过synchronized要求获取对象的锁。若是对象未被锁住,则迚入拥有者;不然则在进入区等待。一旦对象锁被其余线程释放,当即参与竞争。
拥有者(The Owner):表示某一线程成功竞争到对象锁。
等待区(Wait Set):表示线程经过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
从图中能够看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”
,而其它线程都是 “Waiting Thread”
,分别在两个队列 “ Entry Set”
和 “Wait Set”
里面等候。在 “Entry Set”
中等待的线程状态是 “Waiting for monitor entry”
,而在 “Wait Set”
中等待的线程状态是 “in Object.wait()”
。
先看 “Entry Set”里面的线程。咱们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。