文章用來介紹常用的虛擬機內存監控和虛擬機相關的故障排除工具。 包括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
|
使用示例
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
從左到右的含義分別是:
選項 | 描述 |
---|---|
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 capacity
和Current old space capacity
有疑問,可以參考StackOverFlow
上面的這個提問:jstat: difference between OGC & OC, PGC & PC ,簡單點描述就是 一個代包含的空間不一定只有一個,只是 HotSpot 恰好只有一個。OGC = sum(all OC)
jstat -gcutil
gcutil
和 gccapacity
展現的數據基本相同,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
gccause
和gccause
基本相同,多出了兩個參數,分別表示上一次 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 官方提供了中文文檔: