文章來源: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」隊列。