JDK自帶工具之問題排查場景示例

2022-09-07 02:39:13 字數 4591 閱讀 1848

引言

在j**a世界中,我們的很多開發工作從編碼、除錯到調優都在使用gui工具。我們經常嘗試在本地構建一套和線上一樣的環境從而使得問題能夠重現,進而使用我們常用的工具來排查定位故障。但不幸的是,很多情況下是無法在本地重現線上問題的。例如,我們沒有許可權獲取真實客戶端提交到線上服務端的資料。

問題排查場景

獲取正在執行的jvm列表

使用jcmd不加任何引數即可獲取jvm程序列表

25691 org.apache.catalina.startup.bootstrap start

20730 org.apache.catalina.startup.bootstrap start

26828 sun.tools.jcmd.jcmd

3883 org.apache.catalina.startup.bootstrap start

使用jcmd help能夠獲取某個jvm程序其他可用的診斷命令。例如:

[root@test-172-16-0-34-ip ~]# jcmd 3883 help

3883:

the following commands are **ailable:

vm.commercial_features

managementagent.stop

managementagent.start_local

managementagent.start

thread.print

gc.class_histogram

gc.heap_dump

gc.run_finalization

gc.run

vm.uptime

vm.flags

vm.system_properties

vm.command_line

vm.version

help

輸入jcmd 可以執行乙個診斷命令或者獲取到引數錯誤資訊。

[root@test-172-16-0-34-ip ~]# jcmd 3883 gc.heap_dump

3883:

j**a.lang.illegalargumentexception: missing argument for diagnostic command

通過jcmd help 你能夠獲取此診斷命令更多的資訊。如下是gc.heap_dump命令的help。

[root@test-172-16-0-34-ip ~]# jcmd 3883 help gc.heap_dump

3883:

gc.heap_dump

generate a hprof format dump of the j**a heap.

impact: high: depends on j**a heap size and content. request a full gc unless the '-all' option is specified.

syntax : gc.heap_dump [options]

arguments:

filename :  name of the dump file (string, no default value)

options: (options must be specified using the or =syntax)

-all : [optional] dump all objects, including unreachable objects (boolean, false)

j**a堆的dump

jcmd提供了輸出hprof格式的堆dump介面。執行jmcd gc.heap_dump 即可。注意這裡的filename是相對於執行中的jvm目錄來說的,因此避免找不到dump的檔案,這裡推薦使用絕對路徑。此外,也建議使用.hprof作為輸出檔案的副檔名。

在堆dump完成之後,你可以複製此檔案到本地用visualvm或者用jmc的joverflow外掛程式開啟,進而通過分析堆的狀況定位記憶體問題。

需要注意的兩點:

分析類柱狀圖

如果正在排查記憶體洩漏問題,你可能想要知道堆中某種型別的存活物件數目。例如,某一時刻某些類應該只有乙個例項(單例模式),但是此類的另外乙個或者多個例項卻已經到了老年代,但是事實上它們不應該能夠被gc roots訪問到。

執行以下命令可以列印出類柱狀圖(同時也列印出存活物件的數目):

jcmd gc.class_histogram

jmap -histo:live

輸出如下:

num     #instances         #bytes  class name

----------------------------------------------

1:         37083       483****52  [b

2:        235****81       224****84  [c

3:        103958       16069448  

4:        482****61       154****52  j**a.util.hashmap$entry

5:        103958       141****80  

6:          9576       111****68  

7:        186****64       10430784  com.mysql.jdbc.connectionpropertiesimpl$booleanconnectionproperty

8:        274****09        877****88  j**a.util.hashtable$entry

9:          9576        721****52  

10:          7972        6404256  

11:        229****37        551****88  j**a.lang.string

12:         48471        542****52  j**a.net.sockssocketimpl

13:         21599        385****72  [lj**a.util.hashmap$entry;

這裡的以byte為單位的占用大小是淺尺寸(shallow size),並沒有包括子物件的大小。其實這個事實很容易由char和string的統計資料注意到:這倆的例項數目是差不多的,但是char的占用大小要大很多,就是因為string並未包含下面的char的大小。

有了類柱狀圖資訊,你就可以grep/search類的名字從而獲取存活例項的數目。如果你發現某些類的例項數量比期望要大很多,你就可以做heap dump,然後用任意的heap分析工具來分析問題。

執行緒dump

很多時候,應用會呈現出「卡在那裡」的情形。這裡有很多種卡住的狀況:死鎖、cpu密集運算。為了定位到問題所在需要知道執行緒在做什麼、持有了什麼鎖等等。

這裡有三種方法可以列印應用的thread dump。

kill -3 #僅限linux平台

jstack

jcmd thread.print

執行j**a飛行記錄器(j**a flight recorder)

上面講到的工具都是作為快速的檢視診斷工具的。如果要深入分析問題,可以選擇使用內建的j**a飛行記錄器:j**a mission control。

執行jfr需要三步:

1. 建立乙個包含了你自己配置的jfr模板檔案。執行jmc, 然後window->flight recording template manage選單。準備好檔案後,就可以匯出檔案,並移動到要排查問題的環境中。

2. 由於jfr需要jdk的商業證書,這一步需要解鎖jdk的商業特性。

jcmd vm.unlock_commercial_features

3. 最後你就可以啟動jfr。

jcmd jfr.start name=test duration=60s settings=template.jfc filename=output.jfr

上述命令立即啟動jfr並開始使用templayte.jfc的配置收集60s的jvm資訊,輸出到output.jfr中。

一旦記錄完成之後,就可以複製.jfr檔案到你的工作環境使用jmc gui來分析。它幾乎包含了排查jvm問題需要的所有資訊,包括堆dump時的異常資訊。

後記

本文基本上是對英文原文的翻譯,主要描述了幾個常見問題的排查場景。

不得不說的是,jdk自帶的工具是非常強大的。用好了這些工具其實已經足以應付絕大多數的j**a問題排查場景。

使用 JDK自帶工具 keytool生成數字證書

正在為以下物件生成 2,048 位rsa金鑰對和自簽名證書 sha256withrsa 有效期為 99,999 天 cn test,ou wenyao,o r d,l yangpu,st shanghai,c china 正在儲存d test.keystore 儲存在檔案 d test.cer 中的...

windows系統自帶工具

輔助功能嚮導 單擊 開始 執行 在彈出的對話方塊中輸入 accwiz 計算器 單擊 開始 執行 在彈出的對話方塊中輸入 calc 字元影射表 單擊 開始 執行 在彈出的對話方塊中輸入 charmap 磁碟清理 單擊 開始 執行 在彈出的對話方塊中輸入 cleanmgr sql server 客戶端網...

JVM 自帶工具類

作用 儲存jvm實時生成的類 以管理員方式執行cmd j a classpath j a home lib sa jdi.jar sun.jvm.hotspot.hsdb獲取程序id jps l然後在hsdb gui介面上操作 file attach to hotspot process 輸入jps...