前言
之前線上有過一兩次OOM的問題,但是每次定位問題都有點手足無措的感覺名惩,剛好利用星期天驰怎,以測試環(huán)境為模版來學習一下Linux常用的幾個排查問題的命令刃泡。?
也可以幫助自己在以后的工作中快速的排查線上問題潦俺。
jmap命令
jmap -heap pid 輸出當前進程 JVM 堆新生代、老年代狼牺、持久代等請情況羡儿,GC 使用的算法等信息?
jmap -histo:live {pid} | head -n 10 輸出當前進程內(nèi)存中所有對象包含的大小??
jmap -dump:format=b,file=/usr/local/logs/gc/dump.hprof {pid} 以二進制輸出檔當前內(nèi)存的堆情況,然后可以導入 MAT 等工具進行
1是钥、 jmap -heap pid
輸出當前進程JVM堆新生代掠归、老年代、持久代等情況悄泥,GC使用的算法等信息虏冻。?
2、jmap -histo:live {pid} | head -n 10 輸出當前進程內(nèi)存中所有對象包含的大小
輸出當前進程內(nèi)存中所有對象實例數(shù) (instances) 和大小 (bytes), 如果某個業(yè)務對象實例數(shù)和大小存在異常情況弹囚,可能存在內(nèi)存泄露或者業(yè)務設計方面存在不合理之處厨相。?
jmap -dump:
命令如下:?
mkdir logs?
jmap -dump:format=b,file=/tmp/logs/dump.hprof {pid}
-dump:formate=b,file= 以二進制輸出當前內(nèi)存的堆情況至相應的文件,然后可以結合 MAT 等內(nèi)存分析工具深入分析當前內(nèi)存情況鸥鹉。?
也可以通過JVM參數(shù)配置OOM時自動dump當前內(nèi)存鏡像文件蛮穿。 -XX:+HeapDumpOnOutOfMemoryError 和-XX:HeapDumpPath所代表的含義就是當程序出現(xiàn)OutofMemory時,將會在相應的目錄下生成一份dump文件毁渗,而如果不指定選項-XX:HeapDumpPath則在當前目錄下生成dump文件践磅。?
確保應用發(fā)生 OOM 時 JVM 能夠保存并 dump 出當前的內(nèi)存鏡像。?
當然灸异,如果你決定手動 dump 內(nèi)存時音诈,dump 操作占據(jù)一定 CPU 時間片、內(nèi)存資源绎狭、磁盤資源等细溅,因此會帶來一定的負面影響。?
此外儡嘶,dump 的文件可能比較大 , 一般我們可以考慮使用 zip 命令對文件進行壓縮處理喇聊,這樣在下載文件時能減少帶寬的開銷。?
下載 dump 文件完成之后蹦狂,由于 dump 文件較大可將 dump 文件備份至制定位置或者直接刪除誓篱,以釋放磁盤在這塊的空間占用。
dump 日志分析
MAT(Memory Analyzer Tool)凯楔,一個基于 Eclipse 的內(nèi)存分析工具窜骄,是一個快速、功能豐富的 JAVA heap 分析工具摆屯,它可以幫助我們查找內(nèi)存泄漏和減少內(nèi)存消耗邻遏。?
使用內(nèi)存分析工具從眾多的對象中進行分析,快速的計算出在內(nèi)存中對象的占用大小,看看是誰阻止了垃圾收集器的回收工作准验,并可以通過報表直觀的查看到可能造成這種結果的對象赎线。?
具體可以參考:Java內(nèi)存分析工具MAT(Memory Analyzer Tool)安裝使用實例 : https://blog.csdn.net/jin_kwok/article/details/80326088?和?基于Java內(nèi)存dump文件分析解決內(nèi)存泄漏問題 : http://www.reibang.com/p/2cf7169ba1c4
jstack命令
printf '%x\n' tid --> 10 進制至 16 進制線程 ID(navtive 線程) %d 10 進制?
jstack pid | grep tid -C 30 --color ps -mp 8278 -o THREAD,tid,time | head -n 40
某 Java 進程 CPU 占用率高,我們想要定位到其中 CPU 占用率最高的線程糊饱。?
(1) 先利用top命令找到CPU占用高的進程pid?
也可以通過ps -ef | grep 應用名 來快速定位自己應用的pid?
顯示pid:29080?
(2) 利用 top 命令可以查出占 CPU 最高的線程 pid (先找到該pid 29080下所有的線程數(shù)據(jù))?
可以看到占用cpu資源最高的為29173
(3) 占用率最高的線程 ID 為29173垂寥,將其轉換為 16 進制形式 (因為 java native 線程以 16 進制形式輸出)
printf '%x\n' 29173?
(4) 利用 jstack 打印出 java 線程調(diào)用棧信息?
jstack 29080 | grep '0x71f5' -A 50 --color?
可以看到這個線程是在做kafka相關的操作。因為這是測試另锋,所以并不是因為CPU真的占用過高的情況滞项。?
更多內(nèi)容也可以參考:?
如何使用jstack分析線程狀態(tài) : http://www.reibang.com/p/6690f7e92f27?
通過jstack與jmap分析一次線上故障: https://www.cnblogs.com/kingszelda/p/9034191.html
jinfo命令
jinfo可以用來查看正在運行的java運用程序的擴展參數(shù)。?
查看pid對應的JVM參數(shù)夭坪,可以到?PerfMa : http://xxfox.perfma.com/jvm/check?校驗參數(shù)的正確性?
jinfo -flags pid?
拿到Command line后面的配置參數(shù)到perfma中驗證查詢:?
這里面好多功能可以去使用蓖扑。
jstat命令
jstat:Java Virtual Machine statistics monitoring tool JDK自帶的一個輕量級小工具。
jstat顯示GC執(zhí)行的情況
jstat -gc 12538 5000?
即會每5秒一次顯示進程號為12538的java進成的GC情況
說明:?
S0C台舱、S1C律杠、S0U、S1U:Survivor 0/1區(qū)容量(Capacity)和使用量(Used)?
EC竞惋、EU:Eden區(qū)容量和使用量?
OC柜去、OU:年老代容量和使用量?
PC、PU:永久代容量和使用量?
YGC拆宛、YGT:年輕代GC次數(shù)和GC耗時?
FGC嗓奢、FGCT:Full GC次數(shù)和Full GC耗時?
GCT:GC總耗時
顯示內(nèi)容說明如下(部分結果是通過其他其他參數(shù)顯示的,暫不說明):?
S0C:年輕代中第一個survivor(幸存區(qū))的容量 (字節(jié))?
S1C:年輕代中第二個survivor(幸存區(qū))的容量 (字節(jié))?
S0U:年輕代中第一個survivor(幸存區(qū))目前已使用空間 (字節(jié))?
S1U:年輕代中第二個survivor(幸存區(qū))目前已使用空間 (字節(jié))?
EC:年輕代中Eden(伊甸園)的容量 (字節(jié))?
EU:年輕代中Eden(伊甸園)目前已使用空間 (字節(jié))?
OC:Old代的容量 (字節(jié))?
OU:Old代目前已使用空間 (字節(jié))?
PC:Perm(持久代)的容量 (字節(jié))?
PU:Perm(持久代)目前已使用空間 (字節(jié))?
YGC:從應用程序啟動到采樣時年輕代中gc次數(shù)?
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)?
FGC:從應用程序啟動到采樣時old代(全gc)gc次數(shù)?
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)?
GCT:從應用程序啟動到采樣時gc用的總時間(s)?
總結
一般分析CPU或者內(nèi)存異常情況可以通過以下幾步:
查看日志
查看CPU情況
查看TCP情況
查看java線程浑厚,jstack
查看java堆股耽,jmap
通過MAT分析堆文件,尋找無法被回收的對象
參考:?
Java線上問題排查思路與工具使用 : https://blog.csdn.net/GitChat/article/details/79019454