1 頻繁 FullGC/YongGC
查看 gc 日志
jstat -gcutil pid 查看內(nèi)存使用和 gc 情況
2 代碼消耗,如死循環(huán),md5 等內(nèi)存態(tài)操作
1)arthas (已開源:https://github.com/alibaba/arthas)
thread -n 5 查看 CPU 使用率最高的前 5 個線程(包含堆棧,第二部分有詳解)
2)jstack 查找
ps -ef | grep java 找到 Java 進(jìn)程 id
top -Hp pid 找到使用 CPU 最高的線程
printf ‘0x%x’ tid 線程 id 轉(zhuǎn)化 16 進(jìn)制
jstack pid | grep tid 找到線程堆棧
排查方法見常見問題一
2 iowait,等待 IO
vmstat 查看 blocked 進(jìn)程狀況
jstack -l pid | grep BLOCKED 查看阻塞態(tài)線程堆棧
jstack -l pid | grep BLOCKED 查看阻塞態(tài)線程堆棧
profiler dump 線程棧,分析線程持鎖情況
新 new 的對象放在 Eden 區(qū),當(dāng) Eden 區(qū)滿之后進(jìn)行一次 MinorGC,并將存活的對象放入 S0;
當(dāng)下一次 Eden 區(qū)滿的時候,再次進(jìn)行 MinorGC,并將存活的對象和 S0 的對象放入S1(S0 和 S1 始終有一個是空的);
依次循環(huán)直到 S0 或者 S1 快滿的時候?qū)ο蠓湃?old 區(qū),依次,直到 old 區(qū)滿進(jìn)行 FullGC。
jdk1.7 之前 Java 類信息、常量池、靜態(tài)變量存儲在 Perm 永久代,類的原數(shù)據(jù)和靜態(tài)變量在類加載的時候放入 Perm 區(qū),類卸載的時候清理;在 1.8 中,MetaSpace 代替 Perm 區(qū),使用本地內(nèi)存,常量池和靜態(tài)變量放入堆區(qū),一定程度上解決了在運行時生成或加載大量類造成的 FullGC,如反射、代理、groovy 等。
CMSInitiatingOccupancyFraction 表示老年代使用率達(dá)到多少時進(jìn)行 FullGC;
UseCMSCompactAtFullCollection 表示在進(jìn)行 FullGC 之后進(jìn)行老年代內(nèi)存整理,避免產(chǎn)生內(nèi)存碎片。
1)survivor 區(qū)太小,對象過早進(jìn)入老年代。
jstat -gcutil pid 1000 觀察內(nèi)存運行情況;
jinfo pid 查看 SurvivorRatio 參數(shù);
2)大對象分配,沒有足夠的內(nèi)存。
日志查找關(guān)鍵字 “allocating large”;
profiler 查看內(nèi)存概況大對象分布;
實例數(shù)量前十的類:jmap -histo pid | sort -n -r -k 2 | head -10
實例容量前十的類:jmap -histo pid | sort -n -r -k 3 | head -10
dump 堆,profiler 分析對象占用情況
1)fgc 觸發(fā)比例過大,導(dǎo)致老年代占用過多,并發(fā)收集時用戶線程持續(xù)產(chǎn)生對象導(dǎo)致達(dá)到觸發(fā) FGC 比例。
jinfo 查看 CMSInitiatingOccupancyFraction 參數(shù),一般 70~80 即可
2)老年代存在內(nèi)存碎片。
jinfo 查看 UseCMSCompactAtFullCollection 參數(shù),在 FullGC 后整理內(nèi)存
業(yè)務(wù)監(jiān)控
sunfire
eagleeye
日志關(guān)鍵字 “Deadlock found when trying to get lock”
Jstack 或 zprofiler 查看阻塞態(tài)線程
jstack –l pid | grep -i –E 'BLOCKED | deadlock'
dump thread 通過 zprofiler 分析阻塞線程和持鎖情況
mvn dependency:tree 分析報錯方法所在的 jar 包版本,留下新的
arthas:sc -d ClassName
XX:+TraceClassLoading
ClassNotFoundException
NoClassDefFoundError
ClassCastException
-f 跟蹤文件
-i 忽略大小寫
-v 反轉(zhuǎn)查找
-E 擴(kuò)展正則表達(dá)式 :grep -E 'pattern1|pattern2' filename
-b 開啟并發(fā)
-p 指定并發(fā)數(shù)
-A 開啟 askpass
-F 指定分隔符:awk -F “|” '{print $1}‘ | sort -r | uniq -c
時間段匹配:sed '/2020-03-02 10:00:00/,/2020-03-02 11:00:00/p' filename
dashboard:系統(tǒng)實時數(shù)據(jù)面板, 可查看線程,內(nèi)存,gc 等信息
thread:jvm 線程堆棧信息,如查看最繁忙的前 n 線程
getstatic:獲取靜態(tài)屬性值,如 getstatic className attrName 可用于查看線上開關(guān)真實值
sc:查看 jvm 已加載類信息,可用于排查 jar 包沖突
sm:查看 jvm 已加載類的方法信息
jad:反編譯 jvm 加載類信息,排查代碼邏輯沒執(zhí)行原因
watch:觀測方法執(zhí)行數(shù)據(jù),包含出入?yún)?,異常等?/p>
trace:方法內(nèi)部調(diào)用時長,并輸出每個節(jié)點的耗時,用于性能分析
tt:用于記錄方法,并做回放
1 線程池滿
rpc 框架線程池滿
高 RT 接口進(jìn)行線程數(shù)限流
應(yīng)用內(nèi)線程池滿
重啟可短暫緩解,具體還得看問題原因
單機(jī)置換或重啟,可短暫緩解,恢復(fù)看具體原因
集群高且流量大幅增加,擴(kuò)容,恢復(fù)看具體原因
限流
降級
死鎖
kill 進(jìn)程
慢 sql
sql 限流