Jvm故障問題排查以及Jvm調優總結java
爲了學習jvm故障問題的排查,寫了一個例子來驗證,在我以前服務器上部署的一個音樂網站的項目里加了一段代碼。git
輕語音樂網站項目地址:https://github.com/Linliquan/springboot-musicgithub
以下:spring
在一個音樂搜索方法getSongRearch中加了一個for循環,循環一億次建立HashMap對象。springboot
項目啓動部署後,在頁面上模糊搜索歌曲「你」,發現搜索緩慢。服務器
大約十幾秒後才搜索出來jvm
打印的日誌:學習
排查過程:網站
1. 使用 ps -ef | grep java 命令找到相應的進程pid,pid = 24314spa
2. 使用 top 命令,查看cup佔用狀況。如圖,id爲24314的進程,cpu佔用率爲99%
3. 使用 top -Hp pid 命令,查看 pid=24314 進程下的各個線程cpu佔用狀況。
4. 使用 printf "%x" tid 命令,將佔用cpu比較高的線程的 tid = 24335 轉化爲十六進制,34335的十六進制爲 5f0f
5. 使用 jstack pid| grep 十六進制 -A20 命令,如 jstack 24314 | grep 5f0f -A20 打印20行線程的堆棧信息。
grep -A是顯示匹配後和它後面的n行,-B是顯示匹配行和它前面的n行,-C是匹配行和它先後各n行。
如圖能夠看到,MusicLinkController 的 getSongRearch 方法的第180行代碼有問題,而且線程的狀態爲RUNNABLE。
這樣就能夠找出相應有問題的代碼
進一步排查:
1.使用 jmap -histo pid | head 命令,查看堆內存狀況
2.使用 jmap -heap pid,查看堆內存狀況
3.使用 jstat -gc pid 命令,查看各個區內存使用狀況
4.使用 jstat -gcutil 24314命令,查看各區容量使用率,如圖老年代使用率爲96.6%。
5.使用jstat -gc 24314 100 10,每隔100ms打印一次,打印5次
S0C:第一個倖存區的大小 S1C:第二個倖存區的大小 S0U:第一個倖存區的使用大小 S1U:第二個倖存區的使用大小 EC:伊甸園區的大小 EU:伊甸園區的使用大小 OC:老年代大小 OU:老年代使用大小 MC:方法區大小 MU:方法區使用大小 CCSC:壓縮類空間大小 CCSU:壓縮類空間使用大小 YGC:年輕代垃圾回收次數 YGCT:年輕代垃圾回收消耗時間 FGC:老年代垃圾回收次數 FGCT:老年代垃圾回收消耗時間 GCT:垃圾回收消耗總時間
年輕帶分三個區:1個E,2個S區。
1.全部對象在E區分配內存,E區和2個S區初始化爲空
2.E區滿後,對象沒法分配內存,觸發GC
3.第一次GC,就是把E區活對象移到S0區
4.第二次GC,E區和S0區的活對象合併,往S1區轉移
5.第三次GC,E區和S1區的活對象合併,往S0區轉移,此後重複步驟:4,5
6.若是活對象存活時間達到必定長度或者根據動態年齡斷定法,則轉移到年老代。
由下圖中也能夠看得出來
6.設置jvm參數
-Xms :初始堆大小,-Xmn:最大堆大小
7. 使用jmap -heap pid命令,可見新生代爲200M,老年代爲400M,且爲1:2。
jvm參數