1. 程式人生 > 程式設計 >獲取Java執行緒轉儲的常用方法(推薦)

獲取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(執行緒)” 選項卡會顯示“執行緒轉儲”:

獲取Java執行緒轉儲的常用方法(推薦)

2.3 jvisualvm

jvisualvm 是一款客戶端圖形介面工具,既簡單又實用,可用來監控 Java應用程式,對JVM進行故障排查和效能分析。

也可以用來獲取執行緒轉儲。 滑鼠右鍵單擊Java程序,選擇“ Thread Dump”選項,則可以建立執行緒轉儲,完成後會在新選項卡中自動開啟:

獲取Java執行緒轉儲的常用方法(推薦)

2.4 jcmd

jcmd工具本質上是向目標JVM傳送一串命令。 儘管支援很多功能,但不支援連線遠端JVM - 只能在Java程序的本地機器上使用。

其中一個命令是Thread.print,用來獲取執行緒轉儲,示例用法如下:

jcmd 17264 Thread.print

2.5 jconsole

jconsole 工具也可以檢視執行緒棧跟蹤。

開啟jconsole並連線到正在執行的Java程序,導航到“執行緒”選項卡,可以檢視每個執行緒的堆疊跟蹤:

獲取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物件。

方法的布林引數lockedMonitorslockedSynchronizers,表示是否匯出持有的同步器和管程鎖。

5. 總結

我們通過具體示例展示了獲取執行緒轉儲的各種方法。

首先介紹的是各種JDK內建工具,

然後討論了命令列方式,

最後介紹了JMX程式設計的方式。

完整的示例程式碼請參考GitHub倉庫。

到此這篇關於獲取Java執行緒轉儲的常用方法的文章就介紹到這了,更多相關Java執行緒轉儲內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!