OOM:OutOfMemory。內存溢出
cpu 100%: 使用top,查看佔用cpu比較高的進程,使用top -Hp 進程ID ,查看對應的佔用cpu較高的線程。如果是java應用,使用 jstack 導出該線程的堆棧。然後查看哪個方法(棧幀)消耗時間 jstack。
內存飆高: 導出堆內存 jmap,使用jhat 、jvisualvm、mat 等等 進行分析。
如何監控JVM: jstat、jvisualvm 等等
jstack dump
jstack 969 > test.txt : jstack 線程ID > 文件名
8. jinfo pid
9. jstat -gc 動態觀察gc情況 / 閱讀GC日誌發現頻繁GC / arthas觀察 / jconsole/jvisualVM/ Jprofiler(最好用)
jstat -gc 進程ID 500 : 每個500個毫秒打印GC的情況
1:已經上線的系統不用圖形界面用什麼?(cmdline arthas)
2:圖形界面到底用在什麼地方?測試!測試的時候進行監控!(壓測觀察)
10. jmap - histo 進程ID ,查找有多少對象產生
jmap - histo 進程ID | head -20 列出前20個
11. jmap -dump:format=b,file=xxx pid :
線上系統,內存特別大,jmap執行期間會對進程產生很大影響,甚至卡頓(電商不適合)
1:設定了參數HeapDump,OOM的時候會自動產生堆轉儲文件
2:<font color='red'>很多服務器備份(高可用),停掉這臺服務器對其他服務器不影響</font>
3:在線定位(一般小點兒公司用不到)
* 爲什麼需要在線排查?
在生產上我們經常會碰到一些不好排查的問題,例如線程安全問題,用最簡單的threaddump或者heapdump不好查到問題原因。爲了排查這些問題,有時我們會臨時加一些日誌,比如在一些關鍵的函數裏打印出入參,然後重新打包發佈,如果打了日誌還是沒找到問題,繼續加日誌,重新打包發佈。對於上線流程複雜而且審覈比較嚴的公司,從改代碼到上線需要層層的流轉,會大大影響問題排查的進度。
* jvm觀察jvm信息
* thread定位線程問題
* dashboard 觀察系統情況
* heapdump + jhat分析
OOM產生的原因多種多樣,有些程序未必產生OOM,不斷FGC(CPU飆高,但內存回收特別少)
G1
Cset = collectionSet 一組可被回收的分區的集合。
在CSet中存活的數據會在GC過程中被移動到另一個可用分區,CSet中的分區可用來自Eden空間、survivor空間或者老年代。CSet會佔用不到整個堆空間的1%大小。
Rset = RememberedSet 每一個region 中都有一組set,記錄着其它region中的對象到本region的引用。
Rset的價值在於,垃圾回收器不需要掃描整個堆查找誰引用了當前分區中的對象,只需要掃描RSet即可。
新老年代比例 5%-60% 動態。一般不用手工指定,因爲這是G1預測停頓時間的基準。
humongous object :超過單個region的50%
GC何時觸發
YGC: Eden空間不足,多線程並行執行。
FGC:old空間不足,System.gc()
16. G1是否分代?G1垃圾回收器會產生FGC嗎? 是,會。G1 java 10以前是串行FULLGC,之後是並行FullGC
17. 如果G1產生FGC,你應該做什麼?
1. 擴內存
2. 提高CPU性能(回收的快,業務邏輯產生對象的速度固定,垃圾回收越快,內存空間越大)
3. 降低MixedGC觸發的閾值,讓MixedGC提早發生(默認是45%)
G1 中的MixedGC = CMS,初始標記、併發標記、重新標記、並行篩選回收
XX:InitiatingHeapOccupacyPercent 默認值45%。 當YGC超過這個值,啓動MixedGC。在這之前是serial
三色標記
G1使用的是 SATB ,cms 使用的是incremental update。
### GC常用參數
* -Xmn -Xms -Xmx -Xss
年輕代 最小堆 最大堆 棧空間
* -XX:+UseTLAB
使用TLAB,默認打開
* -XX:+PrintTLAB
打印TLAB的使用情況
* -XX:TLABSize
設置TLAB大小
* -XX:+DisableExplictGC
System.gc()不管用 ,FGC
* -XX:+PrintGC
* -XX:+PrintGCDetails
* -XX:+PrintHeapAtGC
* -XX:+PrintGCTimeStamps
* -XX:+PrintGCApplicationConcurrentTime (低)
打印應用程序時間
* -XX:+PrintGCApplicationStoppedTime (低)
打印暫停時長
* -XX:+PrintReferenceGC (重要性低)
記錄回收了多少種不同引用類型的引用
* -verbose:class
類加載詳細過程
* -XX:+PrintVMOptions
* -XX:+PrintFlagsFinal -XX:+PrintFlagsInitial
必須會用
* -Xloggc:opt/log/gc.log
* -XX:MaxTenuringThreshold
升代年齡,最大值15
* 鎖自旋次數 -XX:PreBlockSpin 熱點代碼檢測參數-XX:CompileThreshold 逃逸分析 標量替換 ...
這些不建議設置
### Parallel常用參數
* -XX:SurvivorRatio
* -XX:PreTenureSizeThreshold
大對象到底多大
* -XX:MaxTenuringThreshold
* -XX:+ParallelGCThreads
並行收集器的線程數,同樣適用於CMS,一般設爲和CPU核數相同
* -XX:+UseAdaptiveSizePolicy
自動選擇各區大小比例
### CMS常用參數
* -XX:+UseConcMarkSweepGC
* -XX:ParallelCMSThreads
CMS線程數量
* -XX:CMSInitiatingOccupancyFraction
使用多少比例的老年代後開始CMS收集,默認是68%(近似值),如果頻繁發生SerialOld卡頓,應該調小,(頻繁CMS回收)
* -XX:+UseCMSCompactAtFullCollection
在FGC時進行壓縮
* -XX:CMSFullGCsBeforeCompaction
多少次FGC之後進行壓縮
* -XX:+CMSClassUnloadingEnabled
* -XX:CMSInitiatingPermOccupancyFraction
達到什麼比例時進行Perm回收
* GCTimeRatio
設置GC時間佔用程序運行時間的百分比
* -XX:MaxGCPauseMillis
停頓時間,是一個建議時間,GC會嘗試用各種手段達到這個時間,比如減小年輕代
### G1常用參數
* -XX:+UseG1GC
* -XX:MaxGCPauseMillis
建議值,G1會嘗試調整Young區的塊數來達到這個值
* -XX:GCPauseIntervalMillis
?GC的間隔時間
* -XX:+G1HeapRegionSize
分區大小,建議逐漸增大該值,1 2 4 8 16 32。
隨着size增加,垃圾的存活時間更長,GC間隔更長,但每次GC的時間也會更長
ZGC做了改進(動態區塊大小)
* G1NewSizePercent
新生代最小比例,默認爲5%
* G1MaxNewSizePercent
新生代最大比例,默認爲60%
* GCTimeRatio
GC時間建議比例,G1會根據這個值調整堆空間
* ConcGCThreads
線程數量
* InitiatingHeapOccupancyPercent
啓動G1的堆空間佔用比例
CPU100%排查
1.執行 top 命令,查看佔用cpu使用率最高的 pid 進程
2.使用 top -Hp pid ,鍵入大寫P,按照cpu使用率排序,找出最耗cpu的線程id
3.將線程 id 轉換成 16 進制(堆棧裏面線程id 是16進製表示的)
4.使用 jstack pid | grep '線程id(16進制)' -C5 --color 查看最耗cpu的線程
5.找到對應代碼進行排查。