天天看點

java診斷與調優常用指令jmap、jstack、jstat使用實戰

java應用運作過程中難免會出現問題,特别是在生産環境,發生異常或當機情況,需要診斷與分析,定位原因,進行優化,避免下次再次出現問題。

雖然現在有很多可視化工具,使用起來比指令行更友善,但我們仍需要對基本的指令進行必要的了解。實際上,可視化工具,往往是基于這些基本指令,拿到資料後進行綜合處理後輸出的最終結果。

今天從實戰角度出發,介紹jps、jmap、jstack和jstat這四個指令的常用方式。

jps

作用:擷取java程序号,是後續指令的基礎。

當一台伺服器運作多個java程序時,該指令預設隻輸出程序号和應用名,可能無法區分哪個是自己需要分析的對象,這時候可以附加參數 -l,顯示完整路徑。此外,附加參數-v,可顯示jvm參數。

D:\jdk1.7.0_79\bin>jps
3824 Jps
3832 Bootstrap

D:\jdk1.7.0_79\bin>jps -l
3832 org.apache.catalina.startup.Bootstrap
3820 sun.tools.jps.Jps

D:\jdk1.7.0_79\bin>jps -v
1580 Jps -Dapplication.home=D:\jdk1.7.0_79 -Xms8m
3832 Bootstrap -Djava.util.logging.config.file=D:\MessageCenter\tomcat7\conf\log
ging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManage
r -Xms1024m -Xmx2048m -Djdk.tls.ephemeralDHKeySize=2048 -Dignore.endorsed.dirs=
-Dcatalina.base=D:\MessageCenter\tomcat7 -Dcatalina.home=D:\MessageCenter\tomcat
7 -Djava.io.tmpdir=D:\MessageCenter\tomcat7\temp
           

問題:無效指令

原因:沒有配置環境變量

解決:配置環境變量,或者到jdk對應目錄bin下打開指令視窗

問題:windows環境下java程序存在,但執行jps無結果

原因:windows權限問題,在 Windows系統中,每個 java 程序啟動之後都在

%TMP%/hsperfdata_${user}

(${user}為目前登入使用者名) 目錄下建立一個以該 java 程序 pid 為檔案名的檔案,用以記錄該 java 程序的一些資訊。 通常是因為沒有對這個檔案的讀寫權限而導緻jps指令檢視不到程序。

解決:給目前作業系統使用者,設定足夠權限,注意,有時候需要重新開機作業系統才會令權限生效。

jmap

擷取java程序記憶體情況。

常用指令:jmap -heap [程序ID]

作用:顯示堆資訊

D:\jdk1.7.0_79\bin>jmap -heap 3832
Attaching to process ID 3832, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize      = 2147483648 (2048.0MB)
NewSize          = 1310720 (1.25MB)
MaxNewSize       = 17592186044415 MB
OldSize          = 5439488 (5.1875MB)
NewRatio         = 2
SurvivorRatio    = 8
PermSize         = 21757952 (20.75MB)
MaxPermSize      = 85983232 (82.0MB)
G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 268959744 (256.5MB)
used     = 38999632 (37.19294738769531MB)
free     = 229960112 (219.3070526123047MB)
14.500174420154117% used
From Space:
capacity = 44564480 (42.5MB)
used     = 40604768 (38.723724365234375MB)
free     = 3959712 (3.776275634765625MB)
91.11464556525735% used
To Space:
capacity = 44564480 (42.5MB)
used     = 0 (0.0MB)
free     = 44564480 (42.5MB)
0.0% used
PS Old Generation
capacity = 716177408 (683.0MB)
used     = 8192 (0.0078125MB)
free     = 716169216 (682.9921875MB)
0.0011438506588579795% used
PS Perm Generation
capacity = 22544384 (21.5MB)
used     = 22498624 (21.45635986328125MB)
free     = 45760 (0.04364013671875MB)
99.7970226199128% used

15643 interned Strings occupying 1319328 bytes.
           

常用指令:jmap -histo [程序ID]

作用:按類型顯示執行個體個數及占用空間,可用于排查異常情況,如記憶體洩露引發的大量對象占用記憶體不釋放。

java診斷與調優常用指令jmap、jstack、jstat使用實戰

四列含義依次是序号、執行個體數量、占用空間、對應類名,注意如下特殊标記代表含義

[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]

常用指令:jmap -dump:format=b,file=20230214.dump [程序ID]

作用:生成堆的dump檔案,用于記憶體使用情況進一步分析,通常會輔助以dump檔案分析工具。

jstack

檢視線程情況。

常用指令:jstack [程序ID]

作用:顯示堆棧資訊,通常用于檢視是否存在死鎖。

java診斷與調優常用指令jmap、jstack、jstat使用實戰

結合其他指令,找出占用cpu最高的堆棧資訊(以下步驟僅适用于linux)

1.使用指令top -p [程序ID] ,顯示你的java程序的記憶體情況,比如3832

2.按H,擷取每個線程的記憶體情況

3.找到記憶體和cpu占用最高的線程tid,比如4977

4.轉為十六進制得到 0x1371

5.執行jstack 3832| grep -A 10 1371,得到線程堆棧資訊中1371這個線程所在行的後面10行

6.檢視對應的堆棧資訊找出可能存在問題的代碼

jstat

jstat指令可以檢視堆記憶體各部分的使用量,以及加載類的數量。

jstat [-指令選項] [程序ID] [間隔時間(毫秒)] [查詢次數]

常用指令: jstat -gc pid [interval] [count]

作用:垃圾回收統計

該指令是按容量顯示,切換成百分比則更直覺,指令如下:jstat -gcuitl pid [interval] [count]

java診斷與調優常用指令jmap、jstack、jstat使用實戰

使用該指令,可檢視新生代(伊甸園、兩個幸存區)、老年代的記憶體使用情況,垃圾回收頻率。