目錄
正文
【參考文章】:jstack 命令使用經驗總結
1. 簡介
jstack主要用於生成java虛擬機當前時刻的線程快照。
線程快照是當前java虛擬機內每一條線程正在執行的方法堆棧的集合,
主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等
2. 基本用法
2.1 jstack <pid>
輸出當前時刻該進程的線程快照信息;
一般分爲三個部分:
第一部分爲是當前快照的時間信息和JVM的信息;
示例:
第二部分爲多個線程的執行情況,我們選取一個線程作爲示例進行分析;
示例:
main:線程名稱;
prio:線程優先級;
os_prio:線程優先級;
tid:線程ID;
nid:映射到Linux系統中的輕量級進程PID,快照中用16進製表示,可轉爲10進制在系統中進行查看;
線程當前動作:
一般記錄在每個 thread dump 的第一行末尾;
runnable:表示線程在參數CPU競爭,可能在被調度運行,也可能在就緒等待;
sleeping:表示調用了 Thread.sleep(),線程進入休眠;
waiting on condition [0x...]:表示線程被阻塞原語所阻塞, 方括號內的地址表示線程等待的資源地址; 這種和 jvm 的內置鎖體系沒有關係, 它是 jdk5 之後的 java.util.concurrent.locks.Condition 包下的鎖機制;
waiting for monitor entry [0x...]:表示線程在試圖獲取內置鎖, 進入了等待區 Entry Set, 方括號內的地址表示線程等待的資源地址;
in Object.wait() [0x...]: 表示線程調用了 object.wait(), 放棄了內置鎖, 進入了等待區 Wait Set, 等待被喚醒, 方括號內的地址表示線程放棄的資源地址;
Thread.State:
RUNNABLE:這種一般與線程動作 runnable 一起出現;
BLOCKED (on object monitor): 這種一般與線程動作 waiting for monitor entry 一起出現, 不過在其線程調用棧最末端並沒有一個固定的方法, 因爲 synchronized 關鍵字可以修飾各種方法或者同步塊;
WAITING (on object monitor) 或者 TIMED_WAITING (on object monitor): 這種一般與線程動作 in Object.wait() [0x...] 一起出現, 並且線程調用棧的最末端調用方法爲 at java.lang.Object.wait(Native Method), 以表示 object.wait() 方法的調用;
另外, WAITING 與 TIMED_WAITING 的區別在於是否設置了超時中斷, 即 wait(long timeout) 與 wait() 的區別;
WAITING (parking) 或者 TIMED_WAITING (parking): 這種一般與線程動作 waiting on condition [0x...] 一起出現, 並且線程調用棧的最末端調用方法一般爲 at sun.misc.Unsafe.park(Native Method);
Unsafe.park 使用的是線程阻塞原語, 主要在 java.util.concurrent.locks.AbstractQueuedSynchronizer 類中被使用到, 很多基於 AQS 構建的同步工具, 如 ReentrantLock, Condition, CountDownLatch, Semaphore 等都會誘發線程進入該狀態;
另外, WAITING 與 TIMED_WAITING 的區別與第三點中提到的原因一致;
線程的重要調用修飾:
thread dump 的線程調用棧中, 一般會把與鎖相關的資源使用狀態以附加的形式作重點修飾, 這與線程的動作及狀態有着密切的聯繫, 一般情況下可分爲如下幾類:
locked <0x...>, 表示其成功獲取了內置鎖, 成爲了 owner;
parking to wait for <0x...>, 表示其被阻塞原語所阻塞, 通常與線程動作 waiting on condition 一起出現;
waiting to lock <0x...>, 表示其在 Entry Set 中等待某個內置鎖, 通常與線程動作 waiting for monitor entry 一起出現;
waiting on <0x...>, 表示其在 Wait Set 中等待被喚醒, 通常與線程動作 in Object.wait() [0x...] 一起出現;
第三部分爲JVM級別的信息
示例:
VM Thread:虛擬機線程;
VM Periodic Task Thread:虛擬機的工作任務線程;
JNI global references :JNI 全局引用個數;
2.2 jstack -F -m -l <pid>
-F:進程沒有響應時強制打印堆棧信息;
-m:打印 Java 和 native C、C++ 的堆棧信息;
-l:打印關於鎖的附加信息
當使用 -F -m 參數時,都會進行死鎖的檢測,打印的 thread dump 信息會包含如下信息:
當使用 -l 參數時,輸出當前線程持有的鎖的地址和類型,沒有則顯示爲None: