JVM-探究(四):虛擬機監控和分析工具

文章用來介紹常用的虛擬機內存監控和虛擬機相關的故障排除工具。 包括JDK自帶的命令行工具、和一些可視化工具,如jvisualvm

命令行工具

JDK一些常用的命令行工具,能夠讓你不安裝、不需要在服務器輸出文件拷貝到本地的在進行分析,從而能夠快速地查看虛擬機參數,了解虛擬機當前的運行狀況,十分實用。本問介紹的命令都需要在 JDK8 或以上的環境運行,如果在低于 JDK8 可能會有部分指標亂碼。

命令一覽

名稱 主要作用
jps JVM Process Status Tool, 顯示系統內所有的 HotSpot 進程。 注意:只顯示當前用戶的
jstat JVM Statistics Monitoring Tool, 用于收集 HotSpot 虛擬機各方面的參數
jinfo Configuration Info for Java, 顯示虛擬機配置信息
jmap Memory Map for Java,生成虛擬機的內存轉儲快照片
jhat JVM Heap Dump Browser,用于分析heapdump文件,他會建立一個 HTTP/HTML 服務器,讓用戶可以在榴瀏覽器上查看分析結果
jstack Stack Trace for Java, 顯示虛擬機的線程快照

jps

全名:Java Virtual Machine Process Status Tool

主要選項

選項 含義
-q 忽略主類名稱,只輸出 LVMID(一般和進程號相同
-m 打印被傳入到 main() 方法的參數
-l 打印 main 方法的包名,或者運行的 JAR 包的全路徑名
-v 打印傳遞給 JVM 的參數
-V 打印通過 flags file 傳遞給 JVM 的參數
-Joption 因為jps也是運行在 JVM 之上的,這就是傳遞給運行jps的JVM的參數。eg:-J-Xms48m

使用示例

image
image
image
image
image

jstat

全名:Java Virtual Machine statistics monitoring tool

主要選項

選項 作用
-class 監視類裝載、卸載數量、總空間以及類裝載所耗費的時間
-gc 監視Java堆狀況,包括Eden區域、兩個survivor區、老年代、元空間等的容量、已用空間、GC 時間合計等信息
-compiler 輸出 JIT 編譯器編譯過的方法、耗時等信息
-gccapacity 監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用到的最大、最小空間
-gcutil 監視內容與-gc基本相同,但輸出主要關注已使用空間占總空間百分比
-gccause 與 -gcutil 功能一樣,但是會額外輸出導致上一次GC產生的原因
-gcnew 監視新生代 GC 狀況
-gcnewcapacity 監視內容與 -gcnew 基本相同,輸出主要關注使用到的最大、最小空間
-gcold 監視老年代 GC 情況
-gcoldcapacity 監視內容與 -gcold 基本相同,輸出主要關注使用到的最大、最小空間
-gcpermcapacity 輸出永久代使用到的最大、最小空間(JDK8中已經沒有了,并且暫時沒有找到查看metaspace的大小的命令,可以直接使用-gc)
-printcompilation 輸出已經被 JIT 編譯過的方法

使用示例

jstat -class

image

從左到右的含義分別是:

選項 描述
Loaded 已經加載的類數量
Bytes 已經加載類大小
Unloaded 卸載的類數量
Bytes 卸載的類大小
Time 類加載和卸載操作消耗的時間

jstat -compiler

~ jstat -compiler  50674
Compiled Failed Invalid   Time   FailedType FailedMethod
   1248      0       0     1.36          0

從左到右的含義分別是:

選項 描述
Compiled JIT 編譯任務的數量
Failed JIT 失敗的編譯任務
Invalid 無效的 JIT 編譯任務
Time 編譯需要的時間
FailedType 最后一個編譯失敗的原因
FailedMethod 最后一個編譯失敗的類名和方法

jstat -gc

jacob@JacobMBPlocal~ jstat -gc  50674
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10752.0 10752.0  0.0   5396.8 65536.0  24964.9   175104.0     80.0    17536.0 17112.7 2176.0 2040.8      1    0.006   0      0.000    0.006

從左到右的含義分別是:

選項 描述
SOC S0 區域總大小
S1C S1 區域總大小
S0U S0 區域使用大小
S1U S1 區域使用大小
EC Eden 總大小
EU Eden 區域使用大小
OC 當前 Old Space 總大小
OU Old Space 使用大小
PC 當前 Permanent Space 總大小
PU Permanent Space 使用大小
YCG 新生代 GC 發生次數
YGCT 新生代 GC 時間
FGC full GC 次數q
FGCT full GC 時間
GCT 垃圾回收時間總和

jstat -gccapacity

~ jstat -gccapacity  50674
NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
87040.0 238592.0  87040.0 10752.0 10752.0  65536.0   175104.0   478208.0   175104.0   175104.0      0.0 1064960.0  17536.0      0.0 1048576.0   2176.0      1     0

從左到右的含義分別是:

選項 描述
NGCMN 新生代使用到的最小空間。 Minimum new generation capacity (KB).
NGCMX 新生代使用到的最大空間。Maximum new generation capacity (KB).
NGC 當前新生代大小。Current new generation capacity (KB).
S0C 當前 S0 區域大小。Current survivor space 0 capacity (KB).
S1C 當前 S1 區域大小。Current survivor space 1 capacity (KB).
EC 當前 Eden 區域大小。Current eden space capacity (KB).
OGCMN 老年代使用到的最小空間大小。Minimum old generation capacity (KB).
OGCMX 老年代使用到的最大空間大小。Maximum old generation capacity (KB).
OGC 當前老年代大小。Current old generation capacity (KB).
OC 當前老年代空間大小。Current old space capacity (KB).
PGCMN 永久代使用到的最小空間。Minimum permanent generation capacity (KB).
PGCMX 永久代使用到的最大空間。Maximum Permanent generation capacity (KB).
PGC 當前永久代大小。Current Permanent generation capacity (KB).
PC 當前永久空間大小。Current Permanent space capacity (KB).
VGC Young GC 次數。 Number of Young generation GC Events.
FGC Full GC 次數。Number of Full GC Events.

如果讀者對于 Current old generation capacityCurrent old space capacity 有疑問,可以參考StackOverFlow上面的這個提問:jstat: difference between OGC & OC, PGC & PC ,簡單點描述就是 一個包含的空間不一定只有一個,只是 HotSpot 恰好只有一個。 OGC = sum(all OC)

jstat -gcutil

gcutilgccapacity 展現的數據基本相同,gccapacity 只是一個是精確的數據,gcutil 是更加直觀的百分比。

$ jstat -gcutil 17931
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00   7.25   9.64   3.52  98.53  96.94    385    6.771     6    0.517    7.288

從左到右的含義分別是:

選項 描述
S0 S0 區空間占用百分比。Survivor space 0 utilization as a percentage of the space's current capacity.
S1 S1 區空間占用百分比。Survivor space 1 utilization as a percentage of the space's current capacity.
E Eden 區空間占用百分比。Eden space utilization as a percentage of thespace's current capacity.
O 老年代空間占用百分比。Old space utilization as a percentage of the space's current capacity.
P 永久代空間占用百分比。Permanent space utilization as a percentage ofthe space's current capacity.
YGC Young GC 次數。Number of young generation GC events.
YGCT Young GC 時間。Young generation garbage collection time.
FGC Full GC 次數。Number of Full GC events.
FGCT Full GC 時間。Full garbage collection time.
GCT 總的 GC 時間。Total garbage collection time.

jstat -gccause

gccausegccause基本相同,多出了兩個參數,分別表示上一次 GC 的原因,和本次 GC 的原因。

$ jstat -gccause 17931
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  5.30   0.00  40.79   3.82  98.34  95.90    438    7.501     6    0.517    8.018 Allocation Failure   No GC

新增的兩個參數:

選項 描述
LGCC 上次 GC 的原因。Cause of last Garbage Collection.
GCC 本次 GC 的原因。Cause of current Garbage Collection.

jstat -gcnew

新生代統計

$ jstat -gcnew 17931
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
52416.0 52416.0    0.0 2820.6 15  15 26208.0 419456.0 321595.5    453    7.662
選項 含義
SOC 當前 S0 區域大小。Current survivor space 0 capacity (KB).
S1C 當前 S1 區域大小。Current survivor space 1 capacity (KB).
S0U S0 占用大小。Survivor space 0 utilization (KB).
S1U S1 占用大小。Survivor space 1 utilization (KB).
TT Tenuring 閾值。Tenuring threshold.
MTT 最大 Tenuring 閾值。Maximum tenuring threshold.
DSS 需要的S區域大小。Desired survivor size (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
VGC Number of young generation GC events.
VGCT Young generation garbage collection time.

Tenuring 閾值是動態變化的,最大 Tenuring 閾值可以通過 JVM 參數設置。具體可以參考我的另外一篇博客 Tenuring Threshold 是動態變化的

DSS 為需要的 S 空間的大小,如果實際空間不足,新生代的對象會提前進入老年代。提前轉移實驗

jstat -gcnewcapacity

$ jstat -gcnewcapacity 17931
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
  524288.0   524288.0   524288.0  52416.0  52416.0  52416.0  52416.0   419456.0   419456.0   486     6
選項 描述
NGCMN 新生代最大空間大小。Minimum new generation capacity (KB).
NGCMX 新生代最小空間大小。Maximum new generation capacity (KB).
NGC 當前新生代空間大小。Current new generation capacity (KB).
S0CMX S0 區域最大空間大小。Maximum survivor space 0 capacity (KB).
S0C S0 區域當前空間大小。Current survivor space 0 capacity (KB).
S1CMX S1 區域最大空間大小。Maximum survivor space 1 capacity (KB).
S1C S1 區域當前空間大小。Current survivor space 1 capacity (KB).
ECMX Eden 區域最大空間大小。Maximum eden space capacity (KB).
EC Eden 區域當前空間大小。Current eden space capacity (KB).
YGC Young GC 次數。Number of young generation GC events.
FGC Full GC 次數。Number of Full GC Events.

jstat -gcold

$ jstat -gcold 17931
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
102248.0 100603.7  10324.0   9900.6   1572864.0     63154.7    497     6    0.517    8.744
選項 描述
PC 當前永久代大小。Current permanent space capacity (KB).
PU 當前永久代占用。Permanent space utilization (KB).
OC 當前老年代大小。Current old space capacity (KB).
OU 當前老年代占用。Old space utilization (KB).
YGC Young GC 次數。Number of young generation GC events.
FGC Full GC 次數。Number of Full GC events.
FGCT Full GC 時間。Full garbage collection time.
GCT 所有 GC 時間。Total garbage collection time.

jstat -gcoldcapacity

$ jstat -gcoldcapacity 17931
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
  1572864.0   1572864.0   1572864.0   1572864.0   508     6    0.517    8.923
選項 描述
OGCMN 最小老年代大小。Minimum old generation capacity (KB).
OGCMV 最大老年代大小。Maximum old generation capacity (KB).
OGC 當前老年代大小。Current old generation capacity (KB).
OC 當前老年空間大小。Current old space capacity (KB).
YGC Young GC 次數。Number of young generation GC events.
FGC Full GC 次數。Number of Full GC events.
FGCT Full GC 時間。Full garbage collection time.
GCT 所有 GC 時間。Total garbage collection time.

jstat -printcompilation

$ jstat -printcompilation 17931
Compiled  Size  Type Method
   21778   2719    1 com/sankuai/octo/config/model/file_param_t hashCode
選項 描述
Compiled Number of compilation tasks performed.
Size Number of bytes of bytecode for the method.
Type Compilation type.
Method Class name and method name identifying the compiled method. Class name uses "/" instead of "." as namespace separator. Method name is the method within the given class. The format for these two fields is consistent with the HotSpot -XX:+PrintComplation option.

jstat 的額外參數

上述的命令都可以使用類似下面的參數

jstat -gcutil -t 17931 500 100 其中-t表示答應時間戳、17931為 lvmid、500表示間隔 500ms 來輸出信息、 100表示信息條目顯示d的數量。

譬如,下面顯示了10行,顯示時間間隔為500ms

$ jstat -gcutil 17931 500 10
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  9.55   0.00  69.10   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  71.22   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  72.88   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  74.90   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  77.01   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  78.98   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  80.78   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  82.90   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  84.71   4.26  98.34  95.92    552    8.950     6    0.517    9.466
  9.55   0.00  86.85   4.26  98.34  95.92    552    8.950     6    0.517    9.466

jinfo

輸出 Java 配置信息

下面是 Intellj IDEA 的部分輸出信息

jinfo 88747
Attaching to process ID 88747, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Java System Properties:

java.vendor = Oracle Corporation
preload.project.path = /Users/jacob/Developer/IDEA/campaignmanage
sun.java.launcher = SUN_STANDARD
idea.config.path = /Users/jacob/Library/Preferences/IntelliJIdea2017.3
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
sun.nio.ch.bugLevel =
idea.paths.selector = IntelliJIdea2017.3
kotlin.daemon.client.alive.path = "/var/folders/hw/_d9gvls95316wtq_crffgz3w0000gn/T/kotlin-idea-4717993236071674726-is-running"
jnidispatch.path = /Users/jacob/Library/Caches/IntelliJIdea2017.3/compile-server/campaignmanage_7408d958/_temp_/jna-100881631/jna5884254379081076550.tmp
os.name = Mac OS X
sun.boot.class.path = /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/classes
idea.plugins.path = /Users/jacob/Library/Application Support/IntelliJIdea2017.3
java.vm.specification.vendor = Oracle Corporation
java.runtime.version = 1.8.0_131-b11
jna.loaded = true
io.netty.serviceThreadPrefix = Netty
user.name = jacob
kotlin.incremental.compilation = true
idea.home.path = /Applications/IntelliJ IDEA.app/Contents
user.language = zh
jdt.compiler.useSingleThread = true
sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib
java.version = 1.8.0_131
user.timezone = Asia/Shanghai
java.net.preferIPv4Stack = true
kotlin.daemon.enabled =
sun.arch.data.model = 64

java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding = UTF-8
java.specification.version = 1.8
compile.parallel = false
io.netty.noUnsafe = true

VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line:  -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=/Users/jacob/Developer/IDEA/campaignmanage -Dpreload.config.path=/Users/jacob/Library/Preferences/IntelliJIdea2017.3/options -Dcompile.parallel=false
選項 描述
參數為空 打印命令行標記和系統屬性
-flags 打印命令行標記
-sysprops 打印Java系統屬性

jmap

下面的工具介紹不再提供例子,讀者感興趣可以自己嘗試

選 項 作 用
-dump 生成 Java 堆轉儲快照。格式為:-dump:[live,]format=b,file=<filename>,其中 live 子參數說明是否只 dump 出存活的對象
-finalizerinfo 顯示在 F-Queue 中等待 Finalizer 想成執行 finalize 方法的對象。只在 Linux/Solaris 平臺下有效。在JDK9 Mac 平臺失敗,JDK8 可以
-heap 顯示 Java 堆詳細信息,如使用哪種回收器、參數配置、分代狀況等。只在 Linux/Solaris 平臺下有效。在JDK9 Mac 平臺失敗,JDK8可以
-histo 顯示堆中對象的統計信息,包括類、實例數量、合計容量
permstat 以ClassLoader為統計口徑顯示永久代內存狀態,只在 Linux/Solaris 平臺下有效。 JDK8以上版本已經廢棄
-F 當虛擬機進程對 -dump 選項沒有響應時,可使用這個選項強制生成 dump 快照。只在 Linux/Solaris 平臺下有效。

jhat

虛擬機堆轉儲快照分析工具,不建議使用, 建議使用 visualVM 等工具進行分析

jstack

Java堆棧跟蹤工具

"線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等都是導致線程長時間停頓的常見原因。線程出現停頓的時候通過jstack來查看各個線程的調用堆棧,就可以知道沒有響應的線程到底在后臺做些什么事情,或者等待著什么資源。"

摘錄來自: 周志明. "深入理解Java虛擬機:JVM高級特性與最佳實踐(第2版)"。 iBooks.

選項 作用
-F 當正常輸出的請求不被響應時,強制輸出線程堆棧
-l 除堆棧外,顯示關于鎖的附加信息
-m 如果調用到本地方法的話,可以顯示C/C++ 的堆棧.(JDK9失敗)

visualVM

visualVM 通過可視化的方式來和命令行的命令進行互補,來分析一些內存占用的趨勢,一些參數的動態變化比命令行工具有著先天的優勢,由于官方文檔比較全面,不再贅述。

visualVM 官方提供了中文文檔:

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容