JVM調優實戰:GC、Parallel、CMS、G1 常用參數,G1介紹、CPU100%排查

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.找到對應代碼進行排查。

參考 https://www.cnblogs.com/heluan/p/9601060.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章