開篇
給一個系統(tǒng)定位問題的時候该酗,知識士嚎、經(jīng)驗是關(guān)鍵基礎(chǔ)莱衩,數(shù)據(jù)是依據(jù),工具是運用知識處理數(shù)據(jù)的手段睹晒。今天這里所說的數(shù)據(jù)包括但不限于異常堆棧括细、JVM運行日志、垃圾回收日志锉试、線程快照呆盖、堆快照等贷笛。如何使用分析工具能提升咱們分析數(shù)據(jù)以及定位并解決問題的效率乏苦。這篇文章主要回顧下JVM中故障排查常用的命令以及案例說明。
常用命令
JDK提供了一系列的用于監(jiān)控洞就、診斷Java進(jìn)程的工具拢驾,它們在JDK安裝目錄bin
目錄下繁疤,我們該如何使用它去得到有用的信息并分析系統(tǒng)問題以及性能瓶頸呢?下面詳細(xì)介紹躁染。
jps:JVM進(jìn)程狀態(tài)工具
在linux下我們肯定使用過ps -ef | grep java
命令查看過正在運行的Java進(jìn)程架忌,
而在java中也提供了類似的命令叹放,此命令可以列出正在運行的虛擬機(jī)進(jìn)程,并顯示虛擬機(jī)執(zhí)行主類名稱以及進(jìn)程的唯一ID埋嵌。
jps幫助文檔:
usage: jps [-help]
jps [-q] [-mlvV] [<hostid>]
Definitions:
<hostid>: <hostname>[:<port>]
執(zhí)行案例:
jps -l
1228 sun.tools.jps.Jps
option參數(shù)說明:
- -q:輸出本地虛擬機(jī)進(jìn)程的ID雹嗦,省略類名稱合是。
- -m:輸出啟動時傳遞給主類main()方法的參數(shù)聪全。
- -l:輸出全類名,如果執(zhí)行的是JAR包吱七,會輸出JAR包路徑鹤竭。
- -v:輸出進(jìn)程的JVM配置參數(shù)臀稚。
jstat:JVM統(tǒng)計信息監(jiān)視工具
此命令可以查看JVM運行狀態(tài)〈芄埽可以顯示本地或者遠(yuǎn)程JVM進(jìn)程中的類加載幕帆、內(nèi)存赖条、垃圾收集、即時編譯等運行時數(shù)據(jù)碱茁。
jstat幫助文檔:
invalid argument count
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines.
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
<count> Number of samples to take before terminating.
-J<flag> Pass <flag> directly to the runtime system.
執(zhí)行案例:
//查看垃圾收集等信息
jstat -gc 1441
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
10752.0 10752.0 0.0 0.0 65536.0 9175.5 175104.0 0.0 4480.0 780.7 384.0 76.6 0 0.000 0 0.000 0.000
option參數(shù)說明:
- -class:監(jiān)視類加載墓贿、卸載數(shù)量蜓氨、總空間以及類裝載的耗時穴吹。
- -compiler:即時編譯器編譯過的方法、耗時等信息代嗤。
- -gc:監(jiān)視Java堆狀態(tài)缠借,包括Eden區(qū)泼返、兩個Survivor區(qū)、老年代渠鸽、永久代的容量徽缚、已用空間革屠、垃圾收集時間合計等信息似芝。
- -gccapacity:內(nèi)容與gc基本類似,但輸出的主要是關(guān)注Java堆各個區(qū)域使用的最大详炬、最小空間寞奸。
- -gccause:與gcutil功能一樣,但是會額外輸出上一次導(dǎo)致垃圾收集產(chǎn)生的原因。
- -gcmetacapacity:JDK8下元數(shù)據(jù)空間統(tǒng)計呻引。
- -gcnew:監(jiān)視新生代垃圾收集信息逻悠。
- -gcnewcapacity:與gcnew類似,輸出使用到的最大单旁、最小空間象浑。
- -gcold:監(jiān)視老年代垃圾收集信息琅豆。
- -gcoldcapacity:與gcold類似茫因,輸出使用到的最大、最小空間驰贷。
- -gcutil:監(jiān)視內(nèi)容與gc類似洛巢,輸出已使用空間占總空間的百分比稿茉。
- -printcompilation:輸出已經(jīng)被即時編譯的方法。
jinfo:Java配置信息工具
可以用來查看正在運行的Java程序的擴(kuò)展參數(shù)城须,包括Java system屬性和JVM命令行參數(shù)糕伐;也可以動態(tài)修改正在運行的JVM參數(shù)蘸嘶。
jinfo幫助文檔:
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message
執(zhí)行案例:
jinfo -flags 18378
Attaching to process ID 18378, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.261-b12
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=262144000 -XX:MaxHeapSize=4164943872 -XX:MaxNewSize=1388314624 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=87031808 -XX:OldSize=175112192 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
option參數(shù)說明:
- no option 輸出全部的參數(shù)和系統(tǒng)屬性
- -flag name 輸出對應(yīng)名稱的參數(shù)
- -flag [+|-]name 開啟或者關(guān)閉對應(yīng)名稱的參數(shù)
- -flag name=value 設(shè)定對應(yīng)名稱的參數(shù)
- -flags 輸出全部的參數(shù)
- -sysprops 輸出系統(tǒng)屬性
jmap:Java內(nèi)存映像工具
jamp命令用于生成堆轉(zhuǎn)儲快照褥蚯。還可以查詢finalize執(zhí)行隊列、Java堆和方法區(qū)的詳細(xì)信息赞庶,例如空間使用率训挡、當(dāng)前使用的是哪一種收集器等。
jmap幫助文檔:
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system
執(zhí)行案例:
jmap -dump:format=b,file=test.bin 1713
Dumping heap to /Users/handexing/test.bin ...
Heap dump file created
參數(shù)說明:
- -dump:生成Java堆轉(zhuǎn)儲快照歧强。格式為
-dump:[live,]format=b,file=<filename>
,其中l(wèi)ive參數(shù)說明是否只dump出存活對象澜薄。 - -finalization:顯示在F-queue中等待Finalizer線程執(zhí)行finalize方法的對象。
- -heap:顯示Java堆詳細(xì)信息摊册。例如哪種回收器肤京、參數(shù)配置、分代情況等忘分。linux平臺下有效。
- -histo:顯示堆中對象統(tǒng)計信息白修,包括類饭庞、實例數(shù)量等。
- -permstat:以classloader為統(tǒng)計口徑顯示永久代內(nèi)存狀態(tài)熬荆。linux平臺下有效舟山。
- -F:當(dāng)JVM對-dump沒有響應(yīng)時,可以使用-F強(qiáng)制生成dump快照卤恳,linux平臺下有效累盗。
jhat:JVM堆轉(zhuǎn)儲快照分析工具
與jmap命令搭配使用,用來分析jmap生成的堆轉(zhuǎn)儲快照突琳。jhat內(nèi)置了一個微型http/web服務(wù)器若债,生成分析后的結(jié)果,可以在瀏覽器中查看(話說回來拆融,實際情況中除非是真沒別的工具可用了蠢琳,否則大多數(shù)人是不會直接用jhat來分析快照的)。也不建議在服務(wù)器上使用jhat镜豹,會損耗服務(wù)器性能傲须。
jhat幫助文檔:
Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
-J<flag> Pass <flag> directly to the runtime system. For
example, -J-mx512m to use a maximum heap size of 512MB
-stack false: Turn off tracking object allocation call stack.
-refs false: Turn off tracking of references to objects
-port <port>: Set the port for the HTTP server. Defaults to 7000
-exclude <file>: Specify a file that lists data members that should
be excluded from the reachableFrom query.
-baseline <file>: Specify a baseline object dump. Objects in
both heap dumps with the same ID and same class will
be marked as not being "new".
-debug <int>: Set debug level.
0: No debug output
1: Debug hprof file parsing
2: Debug hprof file parsing, no server
-version Report version number
-h|-help Print this help and exit
<file> The file to read
For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".
All boolean options default to "true"
執(zhí)行案例:
jhat test.bin
Reading from dump.bin...
Dump file created Sat Feb 8 21:54:58 CST 2021
Snapshot read, resolving...
Resolving 271309 objects...
Chasing references, expect 54 dots......................................................
Eliminating duplicate references......................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
訪問localhost:7000
可以查看分析結(jié)果。
jstack:Java堆棧跟蹤工具
用于生成JVM當(dāng)時的線程快照趟脂。線程快照就是當(dāng)前JVM內(nèi)每一條線程正在執(zhí)行的方法堆棧集合泰讽。生成快照主要用于定位線程長時間停頓的原因,例如死鎖、死循環(huán)已卸、請求資源導(dǎo)致長時間掛起等佛玄。就可以排查到?jīng)]有相應(yīng)的線程到底在干什么。
jstack幫助文檔:
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
執(zhí)行案例:
jstack -l 1713
2021-02-08 20:16:16
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.261-b12 mixed mode):
"DestroyJavaVM" #53 prio=5 os_prio=31 tid=0x00007fa898808800 nid=0x1103 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"http-nio-8080-AsyncTimeout" #51 daemon prio=5 os_prio=31 tid=0x00007fa898a4a000 nid=0x7903 waiting on condition [0x0000700007b0b000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1133)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
option參數(shù)說明:
- -F:正常輸入不被響應(yīng)時累澡,強(qiáng)制輸出堆棧梦抢。
- -m:如果調(diào)用本地方法的話,顯示C/C++的堆棧愧哟。
- -l:除堆棧外奥吩,顯示關(guān)于鎖的附加信息。
案例說明
OOM分析
Java代碼案例:
/**
* @author handx
* @version 1.0.0
* @ClassName Heap.java
* @Description TODO
* @createTime 2021年02月08日 20:47:00
*/
public class HeapOOM {
private static class OOMObject{}
public static void main(String[] args) {
ArrayList<OOMObject> oomObjects = new ArrayList<OOMObject>();
while (true){
oomObjects.add(new OOMObject());
}
}
}
VM opetion配置:
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
或使用jmap命令也可以拉取一份堆轉(zhuǎn)儲文件翅雏。
程序執(zhí)行完畢打印:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to ./java_pid1824.hprof ...
Heap dump file created [27809333 bytes in 0.075 secs]
使用jvisualvm進(jìn)行分析(JDK自帶的工具)將dump文件導(dǎo)入進(jìn)來:
打開類
選項卡人芽,可以看到第一個就是我們自己創(chuàng)建的對象:
也可以查看堆轉(zhuǎn)儲上的線程信息:
這個地方基本上已經(jīng)看出是具體哪一行代碼有問題了望几,該修復(fù)修復(fù)了。
寫在最后
簡單介紹了JVM中常用的命令萤厅,想要熟練使用還要在日常開發(fā)調(diào)試中經(jīng)常使用橄抹,熟能生巧。下次復(fù)習(xí)下怎樣對GC日志分析惕味,希望這篇文章能給大家?guī)韼椭ナ摹O矚g加關(guān)注,后續(xù)持續(xù)更新C印E备!