Java - 手擼線上故障 OOM + CPU居高不下

在這裏插入圖片描述


Pre

當你的應用沒有一套完善的監控告警系統,線上故障了 ,總是很被動,但是還得要定位問題 ,奈何手裏無利器 ,沒辦法只能硬上了,雖然原始,好在有效~

所以原生的命令你需要特別熟悉,故障的時間很寶貴,所以留給我們翻資料的時間並不多 ~

如果你還不是很瞭解JVM提供的診斷命令, 戳這裏–> JVM-10虛擬機性能監控與故障處理工具之【JDK的命令行】


常見故障

OOM

OOM了 , 但是你沒有配置

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dump/heapdump.hprof  -XX:OnOutOfMemoryError=/opt/restart.sh

重要的參數

  1. -XX:+HeapDumpOnOutOfMemoryError : 表示當JVM發生OOM時,自動生成DUMP文件 最重要的參數,剩餘兩個參數可選
  2. -XX:HeapDumpPath : 表示生成DUMP文件的路徑, 可以指定文件名稱, -XX:HeapDumpPath=${目錄}/java_heapdump.hprof。若不指定文件名,默認爲:java_<pid>_<date>_<time>_heapDump.hprof
  3. -XX:OnOutOfMemoryError : 表示OOM時 需要觸發的腳本,比如 重啓動作,發送告警等等 用戶自定義

或者GC很厲害,你懷疑有內存泄漏的地方 要看堆信息

那你需要誰呢?

  1. jmap Java 內存映射工具 + jhat 虛擬機堆轉儲快照分析工具
  2. jmap Java 內存映射工具 + MAT (推薦)

jmap Java 內存映射工具

概述

這裏寫圖片描述


語法及使用

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

jmap的主要選項

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

使用舉例, 對pid=12888的進程輸出dump信息

E:\Program Files\Java\jdk1.8.0_161\bin>jmap -dump:format=b,file=test.bin 12888
Dumping heap to E:\Program Files\Java\jdk1.8.0_161\bin\test.bin ...
Heap dump file created


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"

用法舉例

E:\Program Files\Java\jdk1.8.0_161\bin>jmap -dump:format=b,file=test.bin 12888
Dumping heap to E:\Program Files\Java\jdk1.8.0_161\bin\test.bin ...
File exists

E:\Program Files\Java\jdk1.8.0_161\bin>jhat test.bin
Reading from test.bin...
Dump file created Mon Aug 06 20:49:25 CST 2018
Snapshot read, resolving...
Resolving 244224 objects...
Chasing references, expect 48 dots................................................
Eliminating duplicate references................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

瀏覽器輸入 http://localhost:7000/

這裏寫圖片描述


MAT

jmap導出的堆內存信息,如果有MAT, 更方便直觀 ,推薦


CPU居高不下

傳統步驟

  1. top -c ( -c 顯示整個命令行而不只是顯示命令名 ) ,查看佔用cpu的進程
  2. shift+p 按照CPU消耗大小 給進程排序, 找到對應的PID 【P 根據CPU使用百分比大小進行排序】
  3. top -Hp <PID> 具體佔用cpu利用率最高的線程號tid ,shift+p 按照CPU消耗大小【H 線程模式 】
  4. print "%\n" tid 【將獲取到的線程號轉換成16進制】, 用於導出的線程堆棧中根據該關鍵字查到對應的線程信息
  5. jstack -l <PID> >001.log 多執行幾次 【-l 附帶輸出鎖的信息】
  6. 去log中取查找 第四步中轉換出來的16進制的內容,看看相應的代碼

總結下 ,top 找到 佔用CPU最高的 PID, 然後使用top的H參數 線程模式 ,查找到最佔用CPU的 TID , 這個tid 是十進制的, jstack導出來的tid是16進制,因此需要轉成16進制 ,然後多執行幾次jstack , 如果每次都有這個玩意,基本沒跑了

附送一篇 Java - 死鎖 Dead Lock 定位分析


jstack Java堆棧跟蹤工具

概述

這裏寫圖片描述


語法及使用

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

jstack的主要選項

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

用法舉例

E:\Program Files\Java\jdk1.8.0_161\bin>jstack -l 12888
2018-08-06 21:01:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode):

"DestroyJavaVM" prio=6 tid=0x000000000e1ab800 nid=0x2f80 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"DefaultQuartzScheduler_QuartzSchedulerThread" prio=6 tid=0x000000000e1a9800 nid=0xb5c in Object.wait() [0x000000000f59f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:410)
        - locked <0x0000000762395018> (a java.lang.Object)

   Locked ownable synchronizers:
        - None
......
.......
..........

線上分析工具

https://fastthread.io/

在這裏插入圖片描述


高階工具 Arthas

https://alibaba.github.io/arthas/arthas-tutorials?language=cn

在這裏插入圖片描述

Arthas 是Alibaba開源的Java診斷工具,深受開發者喜愛。

當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決:

  • 這個類從哪個 jar 包加載的?爲什麼會報各種類相關的 Exception?

  • 我改的代碼爲什麼沒有執行到?難道是我沒 commit?分支搞錯了?

  • 遇到問題無法在線上 debug,難道只能通過加日誌再重新發布嗎?

  • 線上遇到某個用戶的數據處理有問題,但線上同樣無法 debug,線下無法重現!

  • 是否有一個全局視角來查看系統的運行狀況?

  • 有什麼辦法可以監控到JVM的實時運行狀態?

  • 怎麼快速定位應用的熱點,生成火焰圖?

Arthas支持JDK 6+,支持Linux/Mac/Winodws,採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。

後續單獨開篇介紹Arthas 這個牛逼的工具的使用及原理。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章