JVM垃圾回收器

小猴子_X發表於2022-02-17

上篇我們知道垃圾回收機制,接下來,我們具體到垃圾回收器,看看JVM到底有哪些垃圾回收器。

一.GC效能指標

不可能三角

  • 吞吐量:執行使用者程式碼的時間佔總執行時間的比例
  • 暫停時間:進行GC時,使用者執行緒被暫停的時間(STW)
  • 記憶體佔用:JAVA堆所佔記憶體的大小,這一點隨著硬體的發展,越來越容易實現

主要矛盾:你要暫停時間短,你就需要頻繁GC。但是多次GC,會導致吞吐量低。現在標準:在保證最大吞吐量的前提下,降低暫停的時間

二.七款垃圾回收器

  • 序列回收器:Serial,Serial Old
  • 並行回收器:ParNew,Parallel Scavenge,Parallel Old
  • 併發回收器:CMS,G1

接下來看它們幾個的關係圖:

 說明:

  • 紅色虛線:jdk8廢棄它們2組的組合
  • 綠色虛線:jdk14棄用Parallel Scavenge和Serial Old組合
  • 青色虛線:jdk14刪除CMS回收器

接下來我們分別進行討論


Serial/Serial Old

  • 最基本,最歷史悠久的回收器
  • 序列回收器,Serial使用在新生代,Serial Old使用在老年代。 新生代採用複製演算法,老年代使用標記壓縮演算法。
  • 這種回收器只有在限定單核cpu才使用,現在已經很少使用了


ParNew

  • 並行回收器,多核情況下比Serial的要高,單核下沒有Serial高。
  • 用在新生代,採用複製演算法。老年代使用Serial Old


Parallel/Parallel Old

  • 吞吐量優先java8預設的垃圾收集器
  • Parallel採用複製演算法,Parallel Old採用標記壓縮演算法
  • Parallel與ParNew不同的是,Parallel目的為了達到一個可控的吞吐量,具有自適應調解策略
    • -XX:+UseAdaptiveSizePolicy: 開啟自適應調節策略,年輕代的大小,eden,s的比例,,晉升老年代等引數會自動調節。在手動調優比較困難的情況下,可以開啟這種模式
  • 適用於後臺運算而不需要太多互動的任務。比如批量處理,訂單處理,工資支付,科學計算等

 三.CMS回收器
  • CMS (Concurrent-Mark-Sweep)
  • 低延遲(低暫停時間),第一款併發回收器,但不代表沒有STW

CMS的回收過程:CMS回收器的過程要比其他的都複雜,主要分為四個階段:

  • 初始標記:只標記GC Roots直接關聯的物件。產生STW
  • 併發標記:從GC Roots直接關聯的物件開始,向下遍歷物件圖。不產生STW
  • 重新標記:為了修正在併發標記期間,使用者執行緒產生的新的物件。產生STW
  • 併發清除:標記-清除。不產生STW

總結:在初始標記重新標記階段都會暫停使用者執行緒,產生STW,但是STW的時間很短。 其他階段都是併發進行,不產生STW。所以CMS雖然是併發垃圾回收器,但是整體上還是會產生 STW,只是說STW的時間較短。因為最費時的併發標記與清除標記都不需要暫停工作,所以整體 上的低暫停時間的


CMS的缺點

  • 採用標記-清除演算法會產生記憶體碎片
  • 對CPU資源敏感,CPU數量少會導致使用者程式執行速度降低較多。
  • 產生浮動垃圾,浮動垃圾就是在併發標記階段產生的新垃圾。雖然重新標記可以標記一些新產生的垃圾,但是對於GC Roots直接引用的物件(比如new),沒有辦法進行標記。

那為什麼不適應標記-壓縮演算法?

  • 因為在併發清除的時候,使用者執行緒沒有暫停。如果使用標記整理演算法,就需要移動使用者執行緒在記憶體中的位置。要保證使用者執行緒正常使用,前提是它執行的資源不受影響, 所以必須在STW情況下,才可以進行整理。     

總結:關於記憶體碎片雖然也可以設定整理演算法解決,但是效果不好。垃圾回收過程中,必須暫停使用者執行緒的時間。 而現在CMS要進行併發,那麼就導致垃圾回收過程中,使用者執行緒還在製造新的垃圾的現象。 所以CMS後來被移除掉了,就是因為它為了達到低延遲,犧牲了太多東西,也造成了太多的問題。 jdk9.0被移除,但是還可以用。會報錯 。jdk14.0就徹底的被清除了。

四.G1垃圾回收器
  • 分割槽回收器並行與併發,同時還是分代收集(兼顧老年代和年輕代)。
  • 將記憶體分為不同的區域(Region),在可控制的延遲時間下(讓垃圾回收控制在一個時間段內),優先回收垃圾量最大的區域。 在延遲可控的情況下,儘可能獲得高吞吐量。(想著把吞吐量和暫停時間都儘可能的兼顧)
  • 主要是依靠的特色為:分割槽的原因,回收的範圍小。 而且G1會把這些region放在一個優先列表中,每次垃圾回收,會在指定的時間內,收集最有價值的region區域。 達到高效的收集。
  • Region之間是複製演算法,整體上可以看作是標記壓縮演算法

 

 

寄語:堅持也是一種超能力

相關文章