獲取Java線程轉儲的常用方法(推薦)
1. 線程轉儲簡介
線程轉儲(Thread Dump)就是JVM中所有線程狀態信息的一次快照。
線程轉儲一般使用文本格式, 可以將其保存到文本文件中, 然後人工查看和分析, 或者使用工具/API自動分析。
Java中的線程模型, 直接使用瞭操作系統的線程調度模型, 隻進行簡單的封裝。
線程調用棧, 也稱為方法調用棧。 比如在程序執行過程中, 有一連串的方法調用鏈:obj1.method2
調用瞭obj2.methodB
,obj2.methodB
又調用瞭obj3.methodC
。 每個線程的狀態都可以通過這種調用棧來表示。
線程轉儲展示瞭各個線程的行為, 對於診斷和排查問題非常有用。
下面我們通過具體示例, 來演示各種獲取Java線程轉儲的工具, 以及使用方法。
2. 使用JDK自帶的工具
我們一般使用JDK自帶的命令行工具來獲取Java應用程序的線程轉儲。 這些工具都在JDK主目錄的bin文件夾下。
所以, 隻要配置好 PATH 路徑即可。 如果不會配置, 可以參考:JDK環境準備
2.1 jstack 工具
jstack 是JDK內置的一款命令行工具, 專門用來查看線程狀態, 也可以用來執行線程轉儲。
一般先通過jps
或者ps
命令找到Java進程對應的pid, 然後在控制臺中通過pid來輸出線程轉儲。 當然, 我們也可以將輸出內容重定向到某個文件中。
使用jstack工具獲取線程轉儲的基本參數格式為:
jstack [-F] [-l] [-m] <pid>
下面請看具體的演示:
# 1. 查看幫助信息 jstack -help
輸出的內容類似於:
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 pid
會假死, 則可以加上-F
標志-l
選項, 會查找堆內存中擁有的同步器以及資源鎖-m
選項, 額外打印 native棧幀(C和C++的)
例如, 獲取線程轉儲並將結果輸出到文件:
jstack -F 17264 > /tmp/threaddump.txt
使用jps
命令可以獲取本地Java進程的 pid。
2.2 Java Mission Control
Java Mission Control(JMC)是一款客戶端圖形界面工具, 用於收集和分析Java應用程序的各種數據。
啟動JMC後, 首先會顯示本地計算機上運行的Java進程列表。 當然也可以通過JMC連接到遠程Java進程。
可以鼠標右鍵單擊對應的進程, 選擇 “Start Flight Recording(開始飛行記錄)” 。 結束之後, “Threads(線程)” 選項卡會顯示“線程轉儲”:
2.3 jvisualvm
jvisualvm 是一款客戶端圖形界面工具, 既簡單又實用, 可用來監控 Java應用程序, 對JVM進行故障排查和性能分析。
也可以用來獲取線程轉儲。 鼠標右鍵單擊Java進程, 選擇“ Thread Dump”選項, 則可以創建線程轉儲, 完成後會在新選項卡中自動打開:
2.4 jcmd
jcmd工具本質上是向目標JVM發送一串命令。 盡管支持很多功能, 但不支持連接遠程JVM – 隻能在Java進程的本地機器上使用。
其中一個命令是Thread.print
, 用來獲取線程轉儲, 示例用法如下:
jcmd 17264 Thread.print
2.5 jconsole
jconsole 工具也可以查看線程棧跟蹤。
打開jconsole並連接到正在運行的Java進程, 導航到“線程”選項卡, 可以查看每個線程的堆棧跟蹤:
2.6 小結
事實證明, 可以使用JDK中的很多工具來獲取線程轉儲。 讓我們回顧一下, 並總結它們的優缺點:
jstack jmc jvisualvm jcmd jconsole
3. 使用Linux命令
在企業應用服務器中, 出於安全原因, 可能隻安裝瞭 JRE。 這時候沒法使用這些JDK內置的工具。
但還是有辦法獲取線程轉儲。
3.1 使用kill -3
指令
在Unix/Linux之類的系統中, 可以使用kill
命令獲取線程轉儲, 底層實現原理, 則是通過系統調用kill()
將信號參數發送給進程。 這裡需要發送的是-3
信號。
一般先通過jps
找到JAVA進程對應的pid,kill -3
使用示例如下:
kill -3 17264
3.2Ctrl + Break
(Windows)
在Windows操作系統的命令行窗口中, 可使用組合鍵Ctrl + Break
來獲取線程轉儲。 當然, 需要先導航至啟動Java程序的控制臺窗口, 然後同時按下CTRL
鍵和Break
鍵。
需要註意的是, 某些鍵盤是沒有 “Break
” 鍵的。
在這種情況下, 可以組合使用CTRL
,SHIFT
, 以及Pause
鍵。
這兩個命令都可以將線程轉儲打印到控制臺。
4. 通過編程方式使用ThreadMxBean
JMX技術支持各種各樣的花式操作。 可通過ThreadMxBean
來執行線程轉儲。
示例代碼如下:
private static String threadDump(boolean lockedMonitors, boolean lockedSynchronizers) { StringBuffer threadDump = new StringBuffer(System.lineSeparator()); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { threadDump.append(threadInfo.toString()); } return threadDump.toString(); }
上面代碼做的事情很簡單, 先通過ManagementFactory
獲取ThreadMxBean
對象。
方法的佈爾參數lockedMonitors
和lockedSynchronizers
, 表示是否導出持有的同步器和管程鎖。
5. 總結
我們通過具體示例展示瞭獲取線程轉儲的各種方法。
首先介紹的是各種JDK內置工具,
然後討論瞭命令行方式,
最後介紹瞭JMX編程的方式。
完整的示例代碼請參考GitHub倉庫。
到此這篇關於獲取Java線程轉儲的常用方法的文章就介紹到這瞭,更多相關Java線程轉儲內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 一篇文章學會java死鎖與CPU 100%的排查
- 分享Java死鎖的4種排查工具
- 教你如何監控 Java 線程池運行狀態的操作(必看)
- jstack+jdb命令查看線程及死鎖堆棧信息的實例
- Java JVM虛擬機調優詳解