G1垃圾回收器

来源:https://www.cnblogs.com/fourther/archive/2020/04/10/12676575.html
-Advertisement-
Play Games

垃圾回收器的發展歷程 背景 01、 解決的問題 垃圾回收器是 年正式提出, 開始正式支持,在 年作為 預設的垃圾處理器。 在 年的時候, 程式堆的記憶體越來越大,從而導致程式中可存活的活對象越來越多,因此 的`STW G1 STW`帶來的停頓時間太長了 。 在此之前效率也很高,但活對象數量一多, 時間 ...


垃圾回收器的發展歷程

file

背景

01、G1解決的問題

G1垃圾回收器是04年正式提出,12開始正式支持,在17年作為JDK9預設的垃圾處理器。
file

04年的時候,java程式堆的記憶體越來越大,從而導致程式中可存活的活對象越來越多,因此GCSTW時間越來越長。這是G1要解決的主要問題:STW帶來的停頓時間太長了

CMS在此之前效率也很高,但活對象數量一多,STW時間也很長。而且CMS無法解決記憶體碎片化的問題。

G1還解決的問題是:CMSGC後,無法compact記憶體。

02、G1達成的目標

(1)減少由於STW而帶來的程式延遲時間,做到偽實時、低延時、可設定目標;
可設定目標是指能夠設置GC最大STW停頓的時間,G1會儘量達成目的,但不一定達成。

-XX:MaxGCPauseMillis=N

預設情況下是250毫秒

(2)解決CMSGC後,無法壓縮程式記憶體的問題;

(3)在JDK9之後,預設的垃圾處理器就是G1;它適用於堆記憶體較大的情況下(>4~6G);

G1垃圾回收器

一、G1記憶體佈局

G1不再遵循之前的堆中對象的分代排列,而是將堆分成若幹個等大的區域。
file

而是變成:
file

預設是分成2048個區域,-XX:G1HeapRegionSize=N 2048

Humongous:當你分配的一個對象超過一半區域的大小時,這個對象就會被放入這個區域。這個區域屬於老年代區域。

二、G1的介紹

G1垃圾回收器不再回收整個堆,而是選擇一個Collection SetCS)。而且每次GC時,會估計每個Region中的垃圾比例,優先回收垃圾多的Region。這就為什麼被叫做Garbage First演算法。這也是為什麼G1可以控制STW停頓時間的原因。
G1含有三種GC演算法:

  • Full young GC:年輕代GC演算法:STWParallelCopying
  • 老年代GC演算法:Mostly-concurrent markingIncremental compaction
  • Mixed GC:混合GC

三、G1引來的問題

問題描述

G1將年輕代、老年代區域劃分為許多個小區域,增加在GC判斷對象是否為垃圾的難度。比如:

  • 老年代對象可能持有年代代的引用(跨代引用)
  • 不同的Region間的互相引用
    跨代/跨Region引用

假設在Full young GC時,某個年輕代Region對象可能被老年代的某個對象引用,那麼我在回收這個年輕代Region時,怎麼知道這裡面的對象是否被其他Region、老年代引用呢?

問題解決

Remembered SetCard Table
file

1、CardTable
每個Region中分為很多區域,每個區域我們成為CardTable,對應的就是上述藍色區域;每個CardTable有多個entry組成。當對應的記憶體空間發生改變時,就會標記為dirty

2、RememberedSet
Region1CardTable引用Region2CardTable時,Region2RememberedSet就會記錄對應CardTable中的entry,可以根據其找到對應的記憶體區域。

3、解析
當某個記憶體對應進行賦值是,就是對象的set方法,我們可以在這種方法上添加dirty的描述。
這其實就是典型的時間換空間的做法:用額外的空間維護引用信息,這就是占用5~10%的過多記憶體占用。

解決方法的實現

1、Write Barrier介紹
Write barrier是一種向JVM註入的一小段代碼,用於記錄指針變化。比如說object.field = <reference>

JVM開始更新指針時,就經過以下幾步:

  • 標記CardDirty
  • Card存入Dirty Card Queue隊列中

這裡有一個問題:為什麼要放在隊列里,而不是直接去更新RememberedSet呢?
這是因為JVM運行可能會有多個線程並行的修改RememberedSet,這樣就需要花費額外的時間來解決多線程同步問題。而這種更新引用是頻繁的,所以這種額外時間是無法忍受的。

2、Dirty Card Queue
這個隊列有白、綠、黃、紅四個顏色,表示應用線程往這個隊列放任務的狀態。

  • White
    表示沒有應用線程往隊列里放任務,什麼事都不用乾。

  • Green
    此時Refinement線程開始被激活,開始更新RS-XX:G1ConcRefinementGreenZone=N

  • Yellow
    此時全部的Refinement線程都被激活,來更新RS-XX:G1ConcRefinementYellowZone=N

  • Red
    這個時候,應用線程也開始參與排空隊列的工作。-XX:G1ConcRefinementRedZone=N

四、GC演算法的過程

1、Fully young GC

GC的過程

(1)STW
此時會暫停所有堆中的對象,將部分Region拷貝到指定區域。
file

(2)構建Collection Set
fully young GC就是選取所有的EdenSurvivor

(3)掃描GC Roots

(4)更新RememberedSet
排空Dirty Card Queue

(5)Process RS
根據RS找到要GC的對象被哪些對象引用了。

(6)對象拷貝
survivor區域對象的調整。

(7)Reference Processing

額外會做的事

G1記錄每個階段的時間,用於後期自動調優。比如說會記錄EdenSurvivor的數量和GC時間,後期會根據我們之前設定的暫停目標來自動調整Region數量。
但是我們設置暫停目標越短,年輕代的Region數量就越少。但這可能會導致Fully young GC頻繁發生。

2、Old GC

當堆用量達到一定程度時,就會觸發old GC。可以通過以下參數進行設置:

-XX:InitatingHeapOccpancyPercent=45

old GC有一個很大特點就是併發進行的。但它是如何在堆中不斷變化的情況下,確定哪些是要清理的垃圾對象呢?

三色標記演算法

這種演算法實現了在不暫停應用線程的情況下進行併發標記,標記過程過如下:
(1)將GC Root對象記錄為黑色,其直接引用對象記錄為灰色,並將這些灰色對象放入一個隊列中
file
(2)從隊列取出對象,將其標為黑色,將其引用對象記錄為灰色,再放入隊列中
file
(3)直到隊列中無對象為止
file

三色標記演算法的缺點:Lost Object Problem

三色標記演算法並沒有完全將所有的活對象都標記出來,這就是Lost Object Problem問題。比如說:
(1)剛開始時

file

(2)在即將描述將C標為灰色的一剎那

file

此時,C依然是活對象,但是已經無法將其標記了。

(3)結果

file

Lost Object Problem的解決

這種解決辦法還是通過Write barrier技術來解決。當B.c=null,也就是C指針被刪除時,G1還是被認為活對象。

那如果C是新生對象呢?這是老年代GC

Old GC過程

(1)STW
老年代GC會在這個時候,進行一次Fully young GC

(2)恢復應用線程

(3)使用三色標記演算法併發標記(init marking

(4)STW

這時候會有一個Remark階段,主要是解決SATBReference processing
還會有一個Cleanup階段,用於回收全為空的區

(5)恢復應用線程

3、Mixed GC

我們直到CMS最大的缺點就是無法進行壓縮操作,而G1就通過Mixed GC解決了這個問題。

Mixed GC沒有固定觸發條件,他是根據Fully young GC收集的信息和我們配置的時間來決定,是否觸發Mixed GC。它會根據暫停目標,來優先選擇垃圾最多的Old Region來執行。

Mixed GC會選擇若幹個Region進行,預設是選擇1/8Old RegionEden RegionSurvivor Region

Mixed GC的過程跟Fully young GC的過程相同,都是:STWParallelCopying

原博客地址


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • go語言基礎(一) package + package 調用 Go 程式是通過 package 來組織的。 只有 package 名稱為 main 的源碼文件可以包含 main 函數。 個可執行程式有且僅有一個 main 包。 通過 import 關鍵字來導入其他非 main 包。 可以通過 imp ...
  • public class CopyTextByBuf { public static void main(String[] args) { BufferedReader bufr = null; BufferedWriter bufw = null; try { bufr = new Buffere ...
  • 鏡像用法 修改 composer 的全局配置文件(推薦方式) 打開命令行視窗(windows用戶)或控制台(Linux、Mac 用戶)並執行如下命令: composer config -g repo.packagist composer https://packagist.phpcomposer.c ...
  • 緩衝區的出現提高了對數據的讀寫效率。 緩衝區要結合流才可以使用。 在流的基礎上對流的功能進行了增強。 該緩衝區提供了跨平臺的換行符。newLine(); public class BufferedWriterDemo { public static void main(String[] args) ...
  • 作者: "DeppWang" 、 "原文地址" 人生在世,誰不面試。單例模式:一個搞懂不加分,不搞懂減分的知識點 又一篇一抓一大把的博文,可是你真的的搞懂了嗎?點開看看。。事後,你也來一篇。 單例模式是面試中非常喜歡問的了,我們往往自認為已經完全理解了,沒什麼問題了。但要把它手寫出來的時候,可能出現 ...
  • 使用 pip 安裝 pipenv pip install pipenv 拋出錯誤異常 連接超時 time out 解決方案 更換國內資源 操作: 在C:\Users\Administrator\下新建pip文件夾,在創建pip.ini文件,拷貝下麵代碼進去,保存 切換下載源地址為 [global] ...
  • 通俗理解spring源碼(一)—— 容器的基本實現 大家都知道spring的主要功能就是將本來由我們程式員new出來的對象,交給spring管理。這個管理不僅包括實例化的過程,還包括依賴註入等整個bean生命周期的管理。而spring是通過一個容器,來管理所有bean的。 spring容器的概念,和 ...
  • public class CopyText { public static void main(String[] args) { copy_1(); } public static void copy_1() { FileWriter fw = null; FileReader fr = null; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...