天天看點

JVM GC垃圾回收調優

GC調優

使用指令檢視相關參數 java -XX:+PrintFlagsFinal -version | findstr “GC”

JVM GC垃圾回收調優

确定目标

【低延遲】還是【高吞吐量】,選擇合适的回收器

CMS,G1,ZGC => 低延遲

ParallelGC =>高吞吐量

最快的 GC 是不發生 GC

檢視 FullGC 前後的記憶體占用,考慮下面幾個問題

  1. 資料是不是太多?

    resultSet = statement.executeQuery(“select * from 大表 limit n”)

  2. 資料表示是否太臃腫?
    • 對象圖
    • 對象大小
  3. 是否存在記憶體洩漏?
    • static Map map =
    • 軟引用
    • 弱引用
    • 第三方緩存實作 Redis

新生代調優

新生代的特點

  • 所有的 new 操作的記憶體配置設定非常廉價

    TLAB thread-local allocation buffer

  • 死亡對象的回收代價是零
  • 大部分對象用過即死
  • Minor GC 的時間遠遠低于 Full GC
在這裡新生代是不是越大越好?

-Xmn 參數 ,設定新生代的大小

Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery).GC is performed in this region more often than in other regions. If the size for the young generation is too small, then a lot of minor garbage collections are performed. If the size is too large, then only full garbage collections are performed, which can take a long time to complete. Oracle recommends that you keep the size for the young generation greater than 25% and less than 50% of the overall heap size.

為新生代設定堆的初始大小和最大大小(以位元組為機關)。與其他區域相比,在該區域執行GC的頻率更高。如果新生代的大小太小,則會執行大量小的垃圾收集。如果大小太大,則隻執行完整的垃圾回收,這可能需要很長時間才能完成。Oracle建議将新生代的大小保持在總堆大小的25%和50%以下。

在這裡大小的設定:

  • 新生代能容納所有【并發量 * (請求-響應)】的資料
  • 幸存區大到能保留【目前活躍對象+需要晉升對象】
  • 晉升門檻值配置得當,讓長時間存活對象盡快晉升

相關JVM參數

  • -XX:MaxTenuringThreshold=threshold 設定最大門檻值
  • -XX:+PrintTenuringDistribution 列印相關資訊

老年代調優

以 CMS 為例 低延遲高并發

  • CMS 的老年代記憶體越大越好
  • 先嘗試不做調優,如果沒有 Full GC 那麼已經…,否則先嘗試調優新生代
  • 觀察發生 Full GC 時老年代記憶體占用,将老年代記憶體預設調大 1/4 ~ 1/3

相關JVM參數 -XX:CMSInitiatingOccupancyFraction=percent 當老年代占用比例到達多少後出發Full GC進行回收

案例分析

案例1:請求高峰期發生 Full GC,單次暫停時間特别長 (在這裡使用CMS)

答:在CMS當中的重新标記階段會掃描整個的堆記憶體對象,在業務高峰期間,如果新生代對象過多,就會導緻耗時過多,是以在重新标記之前對這個新生代當中的對象進行一次GC垃圾回收,就可以減少重新标記的時間。

案例2:老年代充裕情況下,發生 Full GC (CMS jdk1.7)

答:在jdk1.7以前的版本,由于使用的是永久代,當永久代設定過小就會導緻發生 Full GC ,在jdk1.8之後,使用的是元空間,元空間使用的是作業系統的記憶體空間,就很難導緻Full GC。

案例3:Full GC 和 Minor GC頻繁

答:GC頻繁,很顯然是記憶體空間緊張,是由于新生代的空間設定過小,将新生代的空間調大,就可以避免新生代Minor GC ,同理,在新生代的記憶體空間足夠的時候,晉升的對象就會變少,即Full GC也就不會被頻繁觸發了。