jvm程序執行慢診斷手冊

生產環境最多的幾種事故之一就是程序執行慢,若是是web服務的話,表現就是響應時間長。本文分享,從業多年造成的排查守則。java

診斷步驟

系統資源查看

首先是系統資源查看,並且必須是在第一步。由於不少事故都是最開始慢後面就會出現卡死,被系統殺死,程序拋出異常結束等等狀況,當時的狀態無法保存下來,不行進行復盤,因此第一步先查看系統的資源,若是出現緊張狀況,趕忙把狀態保存。git

top命令

查看基本就是top命令,能夠看到系統cpu,內存等資源狀況。通過查看系統資源大概能夠分爲如下狀況。github

問題:cpu使用率太高。

若是發現cpu成爲了瓶頸的話,必須立刻進行線程狀況和當時cpu佔用狀況的保存。在糟糕的狀況下,cpu可能被佔滿,那時候ssh都登陸不上去了,就無法獲取當時的狀況。web

使用top -Hp pid獲取線程cpu使用率高的tid
printf "%x\n" tid,獲取線程id的16進制主要是爲了在jstack中查看
jstack pid|grep tid(16)算法

而後就會把線程cpu使用率特別高的線程棧打出來,而後能夠分析這段邏輯了。ssh

內存使用率太高或者沒有系統資源佔用太高

jmap -dump:format=b,file=heapdump.bin pidjvm

這裏必須打dump的緣由是res太高,可能出發系統的oom killer,進程可能被系統殺死,此時不獲取,可能進程就會被殺死了。若是不是系統資源問題,堆dump之後也是要用的。工具

堆佔用查看

jstat -gc -h 10 pid 1000
jstat -gcutil -h 10 pid 1000
jstat -gccause -h 10 pid 1000spa

這裏通常是開三個窗口對比看數據的。-gc主要是關注堆的分區總大小。-gcutil主要是關注已使用的百分比。-gccause主要是關注fgc次數,時間以及gc緣由。線程

內存問題的分類就比較多了,形成問題的卡頓的根本實際上是gc問題。stw的時候虛擬機停頓了,致使反應不過來了。

問題:堆內存佔用空間接近滿

這種狀況就利用mat去查看dump分析吧,可能出現內存使用不合理或者內存泄漏,這裏須要根據代碼來分析。

問題:perm,metaspace佔用接近滿

jps -lvm

查看一下jvm參數設置,極可能是參數設置不合理,-XX:MetaspaceSize是發生gc的最小空間,這裏是否是設置過小。MaxMetaspaceSize,MaxPermSize的值是否設置過小。java6若是設置都不小並且還佔滿了,那就得檢測代碼裏是否是在運行時常量池加了字符串。1.7,1.8就考慮是否是業務用了什麼字節碼生成技術,動態作了一些字節碼操做。

問題:system.gc()

gccause查看gc的緣由是system.gc()。須要檢測是否用了rmi,使用了直接內存,或者業務代碼調用了system.gc()。直接內存查看如今沒有現成的工具。可使用我在github上放着的小工具查看。地址以下https://github.com/xpbob/jstatassist

問題:gc頻繁但不是system.gc()

空間都不是特別緊張,可是gc次數頻繁,而且不是system.gc()。那可能就是gc參數設置不對了,例如cms,老年代回收是一個2秒一次的輪訓操做,頗有多是如今的空間佔用每次都是知足gc的條件的,因而出現了這種狀況。

問題:gc時間特別長

gc時間特別長,這個就從gc算法選擇還有內存狀況來協調參數吧。可是有兩個特例,cms和g1。這兩個垃圾回收器都是有單線程回收的算法的可能的,這裏須要gc日誌分析確認。

問題:堆佔用不大,res特別大

這種狀況可能性太大,常見的是jni,jna操做,mmap文件,直接內存使用,jdk的bug。須要根據實際狀況來分析。

問題: 業務問題

若是以上表現都沒有的話,那須要不斷的打jstack去看線程棧的變化。這個只能是結合業務來看。

相關文章
相關標籤/搜索