<optgroup id="6y7f6"><small id="6y7f6"></small></optgroup>

<code id="6y7f6"></code>

  • <p id="6y7f6"><tbody id="6y7f6"><ins id="6y7f6"></ins></tbody></p>
    <code id="6y7f6"><form id="6y7f6"></form></code>

      Loading

      《深入理解Java虛擬機》第三章讀書筆記(三)——經典垃圾回收器

      系列文章目錄和關于我

      一丶概述

      image-20230204114345535

      上圖展示了 經典的垃圾回收器,其中Serial,ParNew,Parallel Scavenge(圖中的Parallel) 作用在新生代Serial Old CMS,Parallel Old作用在老年代,這些垃圾回收器顏色相同表示通常搭配使用。G1,ZGC,Shenandoah垃圾收集器則拋棄了分代收集理論作用于整堆。下面將介紹這些垃圾回收器

      二丶Serial 和 Serial Old

      Serial 是作用在新生代的,使用標記復制算法單線程進行垃圾收集的垃圾回收器(單線程意味著:回收垃圾的時候使用單個線程,并且回收垃圾的時候工作線程也停止)。它是客戶端模式下默認的垃圾收集器,優點點在于簡單高效,對于內存資源受限的環境,它是所有收集器里額外內存消耗最小的,并且沒用線程切換的開銷,因此在單核CPU下Serial表現甚至優于多核CPU。

      Serial OldSerial的老年代版本,使用標記整理算法,除了和Serial搭配使用之外,它還是CMS老年代垃圾回收失敗時的后備預案

      image-20230204120039159

      • -XX:+UseSerialGC :讓虛擬機使用Serial+Serial Old 進行垃圾回收
      • -XX:SurvivorRatio:控制Survivor 和 Eden的比值,如-XX:SurvivorRatio=8 表示Eden:Survivor=8:1

      三丶ParNew

      ParNew 可用認為是Serial的并行版本,作用于新生代,使用標記復制算法,它是激活CMS垃圾回收器之后默認的新生代垃圾回收器。

      ParNew在單核CPU處理器環境中,不會比Serial更高效,因為它存在線程交互的開銷。使用-XX:ParallelGCThreads=n限制垃圾收集的線程數

      使用 -XX:+UseParNewGC 指定使用ParNew + Serial Old的組合,二者配合工作如下圖。

      image-20230204121128813

      四丶Parallel Scavenge

      Parallel Scavenge 和ParNew 類似,作用于新生代,使用標記復制算法。但是它是專注于吞吐量的垃圾收集器。(吞吐量 = 用戶代碼運行時間 / 處理器總消耗時間(用戶代碼時間+GC時間)

      • -XX:+UseParallelGC 虛擬機在Server模式下的默認值,開啟后,使用 Parallel Scavenge + Serial Old的組合

        image-20230204121128813

      • -XX:MaxGCPauseMillis=n 收集器盡可能保證單次內存回收停頓的時間不超過這個值,但是并不保證不超過該值。(如果設置太小將導致Minor GC頻繁)

      • -XX:GCTimeRatio=n 設置吞吐量的大小,取值范圍0-100,假設 GCTimeRatio 的值為 n,那么系統將花費不超過 1/(1+n)的時間用于垃圾收集

      • -XX:+UseAdaptiveSizePolicy 開啟后,無需人工指定新生代的大?。?code>-Xmn)、 Eden和Survivor的比例(-XX:SurvivorRatio)以及晉升老年代對象的年齡(-XX:PretenureSizeThreshold)等參數,收集器會根據當前系統的運行情況自動調整

      五丶Parallel Old

      Parallel Old 是Parallel Scavenge的老年代版本,多線程,使用標記整理算法.-XX:+UseParallelGC 使用 Parallel Scavenge + Serial Old的搭配方式,并不能重復發揮服務器的多處理器并行處理能力。Parallel Old 出現后注重吞吐量的場景可用使用-XX:+UseParallelOldGC選擇Parallel Scavenge + Parallel Old進行搭配使用

      image-20230204123242684

      六丶CMS

      CMS是一種以獲取最短回收停頓時間為目標收集器,使用標記清除算法回收老年代。適合在關注服務響應速度,系統停頓時間的場景中使用,如B/S 系統。CMS的優勢在于它使用了三色標記算法,實現了垃圾回收和用戶線程的并行執行(初始標記和并發重新標記還是需要Stop The World)

      1.CMS回收流程

      • 初始標記

        指的是尋找所有被 GCRoots 引用的對象,該階段需要Stop the World ,這個步驟僅僅只是標記一下 GC Roots 能直接關聯到的對象,并不需要做整個引用的掃描,因此速度很快。

      • 并發標記

        指的是對「初始標記階段」標記的對象進行整個引用鏈的掃描,該階段不需要Stop the World。 對整個引用鏈做掃描需要花費非常多的時間,因此通過垃圾回收線程與用戶線程并發執行,可以降低垃圾回收的時間。這也是 CMS 垃圾回收器能極大降低 GC 停頓時間的核心原因,但這也帶來了一些問題,即:并發標記的時候,引用可能發生變化,因此可能出現錯殺(是垃圾的對象沒用被標記為垃圾,產生浮動垃圾),和錯標(不是垃圾的對象被標記為垃圾的問題

      • 重新標記

        指的是對并發標記階段出現的問題進行校正,該階段需要Stop the World。 這一階段解決并發標記階段發生錯標的問題。

      • 并發清除

        指的是將標記為垃圾的對象進行清除,該階段不需要Stop the World。垃圾回收線程和用戶線程并發進行。(這一步使用標記清除算法,所有可以和用戶線程并行,但是標記清除會產生較多的內存碎片)

      image-20230204130044921

      2.CMS 優點

      并發收集,低停頓

      將原本的標記信息,分為了初始標記,并發標記,重新標記,其中最為耗時的并發標記可以和用戶線程并行,從而提高了垃圾回收的效率。垃圾回收的階段(并發清除)也可以和用戶線程并行,實現了垃圾回收的低停頓。

      3.CMS 缺點

      • 對 CPU 資源消耗較大

        雖然使用多線程進行垃圾收集提升效率,但是也真是由于多線程垃圾收集流程會占用一些處理器的計算能力而導致應用程序變慢,降低吞吐量。

        默認情況下 CMS 啟用的垃圾回收線程數是(CPU數量 + 3)/4,當 CPU 數量越大時,啟用的垃圾回收線程數占比就越小。

        但如果 CPU 數量不足四個的時候,垃圾回收線程占用就達到了 50%,也就是說需要拿 50% 的 CPU 時間來進行垃圾回收。這就會極大地降低系統的吞吐量,這是讓人無法接受的情況。

      • 無法處理浮動垃圾。 由于 CMS 并發標記階段會發生錯標的情況,因此會有一些本該回收的垃圾對象無法被回收。此外在 CMS 進行并發清理的時候,用戶線程同時在運行,也會產生一些浮動垃圾。因此對于 CMS 回收器來說,其需要留出一些空間給這些浮動垃圾存儲,等到下一次垃圾回收才能進行清理。

        可以通過 -XX:CMSInitiatingOccupancyFraction 參數調節老年代空間使用多少之后觸發CMS進行老年代的回收。

        如果在 CMS 運行期間發現預留的內存無法滿足程序需要,就會提示Concurrent Mode Failure錯誤。此時虛擬機采用后備方案:臨時啟用 Serial Old 回收器來重新進行老年代的垃圾回收,這時候 Stop the World 的時間可能就會很長了。

      • 產生空間碎片。 由于 CMS 是基于標記-清除算法實現的回收器,因此其會產生很多空間碎片,這會導致給大對象分配的時候很麻煩,會提前觸發 Full GC??梢允褂?-XX:+UseCMSCompactAtFullCollection(默認是打開的) 參數來讓無法分配連續內存給大對象的時候,讓FullGC觸發的時候進行老年代的整理工作。

        該參數通常和 -XX:CMSFullGCsBeforeCompaction 一起使用,-XX:CMSFullGCsBeforeCompaction 可以控制CMS發生多少次不整理的FullGC后,下一次FullGC進行老年代的整理。

      七丶G1

      Garbage First 簡稱G,它開創了收集器面向局部收集,和基于Region的內存布局。

      1.停頓模型

      停頓模型:支持在長度為M毫秒的時間內,消耗在垃圾回收上的時間大概不超過N毫秒的目標

      G1如何實現這個目標:

      摒棄了面向整個區域(整個新生代,老年代,堆)進行垃圾回收的樊籠。而是面向堆內任何部分來組成Collection Set(CSet)進行回收,而不是看它屬于哪個分代,而是看哪塊內存中存放的垃圾數量多,回收收益最大,這便是G1的Mixed GC。支撐整個目標實現的是G1基于Rigion的堆內存布局

      2.基于Region的堆內存布局

      image-20230204145952893

      可以看出G1也是遵循分代收集理論的,但是堆內存布局不在堅持固定大小以及固定數量的分代區域劃分,而是把堆分為若干個Region,每一個Region可以是Eden,Survivor,Old中一種。其中還存在Humongous用于存儲大對象,如果一個對象超過Region大小的一半,那么視為大對象,G1將這部分區域視作老年代。

      Region的大小可以通過-XX:G1HeapRegionSize進行設置,必須是2的冪次方,且介于1MB~32MB。超過一個Region大小的大對象講分配在N個連續的Humongous中。

      G1每次回收都是回收若干個Region大小的空間,這也可以避免整堆收集,并且會使用一個優先級列表來記錄和跟蹤每個Region中垃圾堆積的價值,價值即回收獲得的空間大小,和回收所需的時間的經驗值。每次垃圾回收都根據-XX:MaxGCPauseMillis(默認200ms)指定的停頓時間,選擇回收價值最大的Region。

      3. G1 如何解決跨代引用垃圾回收的問題

      Region里面存在跨Region引用的問題依據是使用記憶集的思路去解決的。但是G1的記憶集更為復雜,每一個Region存在一個記憶集,這些記憶集會記錄其他Region指向自己的指針,并標記這些指針位于哪些卡頁的范圍內。

      img

      這種結構占用更大的內存,因為如果堆內存太小不太適合使用G1垃圾收集器。

      4.G1 如何解決并發標記階段,用戶線程更改引用關系造成的問題

      G1使用原始快照的方式解決此問題

      當灰色對象要刪除指向白色對象的引用關系時,就將刪除的引用記錄下來,并發掃描結束后,再將這些記錄過引用關系的灰色對象為根,重新掃描一次。

      此外G1還設計了兩個指針稱為TAMS(Top at mark start)用于在并發回收階段,讓用戶線程在此區域分配內存給新對象。G1默認認為這個區域的對象是存活的。

      5. G1 垃圾回收流程

      image-20230204153031175

      1. 初始標記

        標記了從GC Roots可以直接關聯可達的對象。需要Stop the world

      2. 并發標記

        和用戶線程并發執行,從GC Roots開始對堆中對象進行可達性分析,遞歸掃描整個堆里的對象圖,找出要回收的對象、

      3. 最終標記

        需要Stop the world,處理并發標記階段,使用原始快照SATB記錄的對象。

      4. 篩選回收

        更新Region統計信息,對各個Region的對象回收價值和成本進行排序,然后根據用戶期望的停止時間來指定回收計劃,然后選擇多個Region組成Collection Set(CSet)來進行回收,將回收這部分Region中存活的對象復制到空Region中,再清理整個舊Region的全部空間,這部分需要移動對象,依舊需要Stop the world,由多個線程并行完成。

      6.G1 和CMS對比

      6.1 G1優于CMS的點

      • 可以指定最大停頓時間
      • 可以按收益動態確定回收集
      • 篩選回收使用標記復制算法,不會產生內存碎片,可以避免無法分配連續內存而進行下一次收集的情況的發生

      6.2 CMS 由于G1的點

      • CMS的記憶集只有一份,占用內存小,但是G1每一個Region都有記憶集,所有G1占用更多內存

        因此小內存機器上CMS更適合,堆內存足夠大的適合使用G1也是不錯的選擇。

      • CMS使用寫后屏障維護記憶集,并且是直接同步操作(更改引用的同時進行更新卡表)

        而G1為了實現原始快照,還需要使用寫前屏障,因此G1使用消息隊列進行異步處理 記憶集的更新

      posted @ 2023-02-04 16:48  Cuzzz  閱讀(222)  評論(0編輯  收藏  舉報
      欧洲黄色网页链接入口,免费A级毛片无码无遮挡久久影院,a免费黄色网址,国产一级黄色的网站
      <optgroup id="6y7f6"><small id="6y7f6"></small></optgroup>

      <code id="6y7f6"></code>

    1. <p id="6y7f6"><tbody id="6y7f6"><ins id="6y7f6"></ins></tbody></p>
      <code id="6y7f6"><form id="6y7f6"></form></code>