一文帶你摸清JVM性能監(jiān)控铅碍、故障排查以及案例說明

開篇

給一個系統(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)來:

image

打開選項卡人芽,可以看到第一個就是我們自己創(chuàng)建的對象:

image

也可以查看堆轉(zhuǎn)儲上的線程信息:


image

這個地方基本上已經(jīng)看出是具體哪一行代碼有問題了望几,該修復(fù)修復(fù)了。

寫在最后

簡單介紹了JVM中常用的命令萤厅,想要熟練使用還要在日常開發(fā)調(diào)試中經(jīng)常使用橄抹,熟能生巧。下次復(fù)習(xí)下怎樣對GC日志分析惕味,希望這篇文章能給大家?guī)韼椭ナ摹O矚g加關(guān)注,后續(xù)持續(xù)更新C印E备!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末禀倔,一起剝皮案震驚了整個濱河市榄融,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌救湖,老刑警劉巖愧杯,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鞋既,居然都是意外死亡力九,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門邑闺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跌前,“玉大人,你說我怎么就攤上這事陡舅∈嫖” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長臂寝。 經(jīng)常有香客問我章鲤,道長,這世上最難降的妖魔是什么咆贬? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任败徊,我火速辦了婚禮,結(jié)果婚禮上掏缎,老公的妹妹穿的比我還像新娘皱蹦。我一直安慰自己,他們只是感情好眷蜈,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布沪哺。 她就那樣靜靜地躺著,像睡著了一般酌儒。 火紅的嫁衣襯著肌膚如雪辜妓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天忌怎,我揣著相機(jī)與錄音籍滴,去河邊找鬼。 笑死榴啸,一個胖子當(dāng)著我的面吹牛孽惰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸥印,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼勋功,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了库说?” 一聲冷哼從身側(cè)響起酝润,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎璃弄,沒想到半個月后要销,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡夏块,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年疏咐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脐供。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浑塞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出政己,到底是詐尸還是另有隱情酌壕,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站卵牍,受9級特大地震影響果港,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糊昙,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一辛掠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧释牺,春花似錦萝衩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至祭刚,卻和暖如春牌捷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袁梗。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工宜鸯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留憔古,地道東北人遮怜。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像鸿市,于是被迫代替她去往敵國和親锯梁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容