JVM 第五篇:命令行 JVM 故障處理工具

?本文內(nèi)容過(guò)于硬核,建議有 Java 相關(guān)經(jīng)驗(yàn)人士閱讀。
?
1. 引言
雖然我們前面介紹了各種圖形化 JVM 故障處理工具,但是很多情況下,我們?cè)谔幚韱?wèn)題的時(shí)候并沒(méi)有圖形化的操作環(huán)境可以使用,這時(shí)候,就需要用到 JDK 為我們提供的命令行工具了。
2. jps: 虛擬機(jī)進(jìn)程狀況工具
jps 絕對(duì)是使用頻率最高的 JDK 命令行工具,它的作用是可以列出正在運(yùn)行的虛擬機(jī)進(jìn)程,并顯示虛擬機(jī)執(zhí)行主類(lèi)( Main Class , main() 函數(shù)所在的類(lèi))名稱(chēng)以及這些進(jìn)程的本地虛擬機(jī)唯一 ID ( LVMID , LocalVirtual Machine Identifier )。
命令格式:
jps?[options?]?[?hostid?]?
執(zhí)行樣例:
PS?D:\>?jps?-l
5200?org.jetbrains.jps.cmdline.Launcher
16868?jdk.jcmd/sun.tools.jps.Jps
19368?org.jetbrains.idea.maven.server.RemoteMavenServer36
可以看到我本機(jī),有三個(gè) JVM 進(jìn)程, 5200 和 19368 是軟件 IDEA 的進(jìn)程,從類(lèi)名上是可以看出來(lái)的,還有一個(gè)是 jps 本身的這個(gè) JVM 進(jìn)程。
列舉一些常用參數(shù):
| 可選項(xiàng) | 作用 |
|---|---|
| -l | 輸出完全的包名,應(yīng)用主類(lèi)名,jar的完全路徑名。 |
| -q | 僅輸出 VM 標(biāo)識(shí)符,不包括 classname , jar name , arguments in main method 。 |
| -m | 輸出 main method 的參數(shù)。 |
| -v | 輸出 JVM 參數(shù)。 |
3. jstat: 虛擬機(jī)統(tǒng)計(jì)信息監(jiān)視工具
jstat(JVM Statistics Monitoring Tool) 是用于監(jiān)視虛擬機(jī)各種運(yùn)行狀態(tài)信息的命令行工具。
位于 JDK 的 bin 目錄下,主要利用 JVM 內(nèi)建的指令對(duì) Java 應(yīng)用程序的資源和性能進(jìn)行實(shí)時(shí)的命令行的監(jiān)控,包括了對(duì) Heap size 和垃圾回收狀況的監(jiān)控。
jstat 工具特別強(qiáng)大,有眾多的可選項(xiàng),詳細(xì)查看堆內(nèi)各個(gè)部分的使用量,以及加載類(lèi)的數(shù)量。使用時(shí),需加上查看進(jìn)程的進(jìn)程 id ,和所選參數(shù)。參考格式如下:
jstat?-options?
可以列出當(dāng)前 JVM 版本支持的選項(xiàng),常見(jiàn)的有:
-class (類(lèi)加載器) -compiler (JIT) -gc (GC堆狀態(tài)) -gccapacity (各區(qū)大小) -gccause (最近一次GC統(tǒng)計(jì)和原因) -gcnew (新區(qū)統(tǒng)計(jì)) -gcnewcapacity (新區(qū)大小) -gcold (老區(qū)統(tǒng)計(jì)) -gcoldcapacity (老區(qū)大小) -gcpermcapacity (永久區(qū)大小) -gcutil (GC統(tǒng)計(jì)匯總) -printcompilation (HotSpot編譯統(tǒng)計(jì))
比如我想查看一下我本地的 IDEA 進(jìn)程的 GC 情況匯總,可以使用命令:
PS?D:\>?jstat?-gcutil?5200
??S0?????S1?????E??????O??????M?????CCS????YGC?????YGCT????FGC????FGCT????CGC????CGCT?????GCT
??0.00??43.29??20.83???0.08??97.05??93.67??????1????0.003?????0????0.000?????-????????-????0.003
查詢(xún)結(jié)果表明:
我的 IDEA 的新生代 Eden 區(qū)( E ,表示 Eden )使用了 20.83% 的空間, 2 個(gè) Survivor 區(qū)( S0 、 S1 ,表示 Survivor0 、 Survivor1 ),S0 是空的,而 S1 使用了 43.29% ,老年代( O ,表示 Old )使用了 0.08% 的空間,元空間( M , 表示 Metaspace )使用了 97.05% 的空間。
程序運(yùn)行以來(lái)共發(fā)生 Minor GC ( YGC ,表示 Young GC ) 1 次,總耗時(shí) 0.003 秒,發(fā)生 Full GC ( FGC ,表示 Full GC )0 次,總耗時(shí)( FGCT ,表示 Full GC Time )為 0 秒,所有 GC 總耗時(shí)( GCT ,表示 GC Time )為 0.003 秒。
4. jinfo: Java 配置信息工具
jinfo(Configuration Info for Java)可以用來(lái)查看正在運(yùn)行的 Java 應(yīng)用程序的擴(kuò)展參數(shù),包括 Java System 屬性和 JVM 命令行參數(shù);也可以動(dòng)態(tài)的修改正在運(yùn)行的 JVM 一些參數(shù)。當(dāng)系統(tǒng)崩潰時(shí), jinfo 可以從 core 文件里面知道崩潰的 Java 應(yīng)用程序的配置信息。
使用 jps 命令的 -v 參數(shù)可以查看虛擬機(jī)啟動(dòng)時(shí)顯式指定的參數(shù)列表,但如果想知道未被顯式指定的參數(shù)的系統(tǒng)默認(rèn)值,除了去找資料外,就只能使用 jinfo 的 -flag 選項(xiàng)進(jìn)行查詢(xún)了。
jinfo 命令格式:
jinfo?[option]?pid
查詢(xún)樣例:
PS?D:\>?jinfo?-flags?5200
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:-UseLargePagesIndividualAllocation?-XX:+UseParallelGC
5. jmap: Java 內(nèi)存映像工具
jmap(Memory Map for Java)命令用于生成堆轉(zhuǎn)儲(chǔ)快照(一般稱(chēng)為 heapdump 或 dump 文件)。
它也可以查看堆內(nèi)對(duì)象示例的統(tǒng)計(jì)信息、查看 ClassLoader 的信息以及 finalizer 隊(duì)列。
jmap 命令格式:
jinfo?[option]?pid
option 可選的參數(shù):
no option:查看進(jìn)程的內(nèi)存映像信息,類(lèi)似 Solaris pmap 命令。 heap:顯示 Java 堆詳細(xì)信息 histo[:live]:顯示堆中對(duì)象的統(tǒng)計(jì)信息 clstats:打印類(lèi)加載器信息 finalizerinfo:顯示在 F-Queue 隊(duì)列等待 Finalizer 線程執(zhí)行 finalizer 方法的對(duì)象 dump: :生成堆轉(zhuǎn)儲(chǔ)快照 F:當(dāng) -dump 沒(méi)有響應(yīng)時(shí),使用 -dump 或者 -histo 參數(shù). 在這個(gè)模式下, live 子參數(shù)無(wú)效. help:打印幫助信息 J :指定傳遞給運(yùn)行 jmap 的 JVM 的參數(shù)
PS?D:\>?jmap?-dump:format=b,file=idea.bin?5200
Dumping?heap?to?D:\idea.bin?...
Heap?dump?file?created
6. jhat: 虛擬機(jī)堆轉(zhuǎn)儲(chǔ)快照分析工具
JDK 提供jhat(JVM Heap Analysis Tool)命令與 jmap 搭配使用,來(lái)分析 jmap 生成的堆轉(zhuǎn)儲(chǔ)快照。jhat 內(nèi)置了一個(gè)微型的 HTTP/Web 服務(wù)器,生成堆轉(zhuǎn)儲(chǔ)快照的分析結(jié)果后,可以在瀏覽器中查看。
使用命令為:
PS?D:\>?jhat?idea.bin
Reading?from?idea.bin...
Dump?file?created?Thu?Oct?08?18:54:37?CST?2020
Snapshot?read,?resolving...
Resolving?147921?objects...
Chasing?references,?expect?29?dots.............................
Eliminating?duplicate?references.............................
Snapshot?resolved.
Started?HTTP?server?on?port?7000
Server?is?ready.
然后在瀏覽器上訪問(wèn)地址 http://localhost:7000/ 可以看到分析結(jié)果,不過(guò)這個(gè)分析工具一般沒(méi)什么人會(huì)用,因?yàn)楣δ芴^(guò)簡(jiǎn)陋了。
相比較而言,我們可以使用 VisualVM 或者 Eclipse Memory Analyzer 再或者 IBM HeapAnalyzer 等工具分析剛才 jmap 產(chǎn)生的 dump 文件。
7. jstack: Java 堆棧跟蹤工具
jstack(Stack Trace for Java)命令用于生成虛擬機(jī)當(dāng)前時(shí)刻的線程快照(一般稱(chēng)為 threaddump 或者 javacore 文件)。
線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合,生成線程快照的目的通常是定位線程出現(xiàn)長(zhǎng)時(shí)間停頓的原因,如線程間死鎖、死循環(huán)、請(qǐng)求外部資源導(dǎo)致的長(zhǎng)時(shí)間掛起等,都是導(dǎo)致線程長(zhǎng)時(shí)間停頓的常見(jiàn)原因。
jstack 命令格式:
jstack?[option]?pid
option 的可選參數(shù):
-F: 當(dāng)正常輸出的請(qǐng)求不被響應(yīng)時(shí),強(qiáng)制輸出線程堆棧。 -l: 除堆棧外,顯示關(guān)于鎖的附加信息。 -m: 如果調(diào)用到本地方法的話(huà),可以顯示 C/C++ 的堆棧。
PS?D:\>?jstack?-l?5200
2020-10-08?19:03:39
Full?thread?dump?Java?HotSpot(TM)?64-Bit?Server?VM?(25.221-b11?mixed?mode):
"DestroyJavaVM"?#13?prio=5?os_prio=0?tid=0x00000000037b8000?nid=0x3f20?waiting?on?condition?[0x0000000000000000]
???java.lang.Thread.State:?RUNNABLE
???Locked?ownable?synchronizers:
????????-?None

