JVM 三色標記算法詳解!

在這里插入圖片描述

目錄

      • 1. 什么是三色標記算法?
        • 三種顏色及其含義:
      • 2. 基礎三色標記算法流程 (非并發)
      • 3. 并發場景下的挑戰:一致性問題
        • 3.1. 漏標 (Missing Live Object) - 最嚴重的問題
        • 3.2. 錯標 (Floating Garbage) - 不那么嚴重的問題
      • 4. 屏障機制 (Barrier) - 解決并發問題
        • 4.1. 寫屏障 (Write Barrier)
        • 4.2. 讀屏障 (Load Barrier)
      • 5. 各GC收集器中的三色標記應用
      • 6. 總結

1. 什么是三色標記算法?

三色標記算法 是一種用于標記存活對象 (Marking Live Objects) 的圖遍歷算法。它將堆中的所有對象劃分為三種顏色,以表示其在可達性分析過程中的不同狀態。通過這種顏色標記,垃圾回收器能夠區分出哪些對象是存活的(即不應被回收),哪些是死亡的(即可以被回收的)。

該算法是并發垃圾回收器(如CMS、G1、ZGC、Shenandoah等)能夠與應用程序線程并行工作的基礎。

三種顏色及其含義:
  1. 白色 (White):

    • 表示對象未被訪問過
    • 在GC開始時,所有對象都是白色的。
    • 在標記階段結束時,仍是白色的對象被視為垃圾對象,將被回收。
    • 可以理解為“待處理”或“已死亡”的對象。
  2. 灰色 (Gray):

    • 表示對象已被訪問過
    • 但它的一個或多個子對象(它引用的對象)還沒有被完全掃描
    • 可以理解為“正在處理中”的對象。
  3. 黑色 (Black):

    • 表示對象已被訪問過
    • 并且它的所有子對象(它引用的對象)也全部被掃描過并標記(要么是灰色,要么是黑色)
    • 可以理解為“已處理完成”且“確認存活”的對象。

2. 基礎三色標記算法流程 (非并發)

為了理解并發場景下的復雜性,我們首先看一個理想化的、非并發(即應用程序停頓)的三色標記過程:

  1. 初始化: GC開始時,將所有對象都標記為白色
  2. 根集掃描: 從GC Roots(如虛擬機棧、本地方法棧、方法區中的靜態變量、常量等)開始,遍歷所有直接被GC Roots引用的對象。將這些對象標記為灰色,并放入一個“待處理列表”(通常是一個隊列)。
  3. 遍歷:
    • 從“待處理列表”中取出一個灰色對象A。
    • 遍歷A的所有子對象(字段引用)。
    • 如果子對象B是白色的,則將B標記為灰色,并將其加入“待處理列表”。
    • 當A的所有子對象都被掃描完畢(并相應地被標記為灰色或黑色)后,將對象A標記為黑色
  4. 重復: 重復步驟3,直到“待處理列表”為空。
  5. 結束: 此時,所有黑色對象都是存活的,所有灰色對象最終都會變成黑色(或在某些特殊情況下,如果其子對象有環,它們自身也會被處理成黑色)。最終,所有仍然是白色的對象即為不可達的垃圾,可以被回收。

3. 并發場景下的挑戰:一致性問題

當三色標記算法在GC與應用程序線程并發運行時,事情變得復雜。應用程序線程(也稱為Mutator)可能會修改對象圖,這可能導致兩種基本的一致性問題:

3.1. 漏標 (Missing Live Object) - 最嚴重的問題

定義: 一個明明是存活的對象,在GC標記結束后卻被錯誤地標記為白色,從而被回收。這是最危險的,因為會導致程序錯誤甚至崩潰。

發生條件: 當以下兩個條件同時滿足時,就會發生漏標:

  1. 應用程序刪除了從“灰色”對象到“白色”對象的引用。 (即A (灰色) 不再引用 C (白色))
  2. 應用程序新增了從“黑色”對象到“白色”對象的引用。 (即B (黑色) 開始引用 C (白色))

舉例說明:
在這里插入圖片描述

假設有對象A(灰色),B(黑色),C(白色)。

  • 初始狀態:GC Roots -> A (灰色已入隊),GC Roots -> B (黑色已處理完畢)。A -> C (C是白色)。
  • GC線程正在遍歷,B已經是黑色(意味著B及其所有子對象都處理完了)。A是灰色(待處理)。
  • 并發過程:
    1. 應用程序線程執行操作:A.field = null; (刪除了 A -> C 的引用)。
    2. 應用程序線程執行操作:B.new_field = C; (新增了 B -> C 的引用)。
  • 結果:
    • A在處理完其子對象后,發現C不再是其子對象,因此C不會通過A的路徑被標記。
    • B已經是黑色,按照三色標記原則,黑色對象不會再被掃描,所以C也不會通過B的路徑被標記。
    • 最終,C仍然是白色,被誤判為垃圾而回收。
3.2. 錯標 (Floating Garbage) - 不那么嚴重的問題

定義: 一個明明是死亡的對象,在GC標記結束后卻被錯誤地標記為黑色,從而沒有被回收。

發生條件: 當以下條件滿足時,會發生錯標:

  • 應用程序刪除了所有從“灰色”或“黑色”對象到“白色”對象的引用。 (即一個對象的所有引用鏈被切斷)
  • GC線程在刪除操作之前已經訪問過該對象,并將其標記為灰色或黑色

舉例說明:
在這里插入圖片描述

假設對象A(灰色)引用了對象C(白色)。

  • 初始狀態:A (灰色已入隊),A -> C (C是白色)。
  • 并發過程:
    1. GC線程正在處理A,A將C標記為灰色并加入待處理列表。
    2. 應用程序線程執行操作:A.field = null; (刪除了 A -> C 的引用,C變得不可達)。
  • 結果: C已經被GC標記為灰色,最終會被標記為黑色。雖然它已經不可達,但GC不知道,將它作為存活對象保留了下來。這種對象被稱為“浮動垃圾”,會在下一次GC周期中被回收。

錯標雖然會增加內存占用,但不會導致程序錯誤,因此通常比漏標更容易接受和處理。


4. 屏障機制 (Barrier) - 解決并發問題

為了解決并發標記中的漏標問題,現代GC引入了屏障機制。屏障是JVM在編譯器或運行時,在應用程序代碼中插入的一小段代碼,用于攔截特定內存操作(讀或寫),從而記錄引用變化信息。

4.1. 寫屏障 (Write Barrier)

寫屏障在對象引用被修改時觸發。它分為:

  1. 增量更新 (Incremental Update) - 基于后寫屏障 (Post-write Barrier)

    • 解決思路: 當一個黑色對象A新增了一個對白色對象C的引用時(B.new_field = C;),認為這種引用關系是新增出來,在標記階段結束時可以重新掃描
    • 工作原理: 當一個黑色對象引用了一個白色對象時,后寫屏障會把這個黑色對象重新標記為灰色,讓GC重新掃描它的子對象,或者將白色對象C標記為灰色加入待處理隊列。
    • 效果: 這種機制確保“黑色對象引用白色對象”的鏈條不會被遺漏。它只避免了漏標,但可能會造成更多的浮動垃圾。
    • 采用者: CMS GC。
  2. 原始快照 (Snapshot At The Beginning, SATB) - 基于前寫屏障 (Pre-write Barrier)

    • 解決思路: 當一個“灰色”對象A刪除一個對“白色”對象C的引用時(A.field = null;),將A在GC開始時指向的引用C記錄下來。
    • 工作原理: 當一個引用即將從另一個引用中消失時(即修改一個對象的引用字段前),前寫屏障會捕捉到被刪除的舊引用,將其指向的對象標記為灰色(即放入待處理隊列)。
    • 效果: 確保在GC標記開始時所有可達的對象都被標記。這種方式避免了漏標,但會產生更多的浮動垃圾(因為即使對象不可達了,只要GC開始時它可達,就會被標記為存活)。
    • 采用者: G1 GC。
4.2. 讀屏障 (Load Barrier)

讀屏障在應用程序讀取對象引用時觸發。它不是直接解決三色標記的漏標問題,而是為了支持更高級的并發機制(如并發對象移動),但在這種機制下,也順帶解決了標記的一致性問題。

  • 解決思路: 應用程序讀取引用時,由屏障檢查并修正引用狀態。
  • 工作原理: 當應用程序讀取到一個對象引用時,讀屏障會攔截該操作,檢查該引用所指向的對象的狀態(通過染色指針或轉發指針)。如果對象在GC過程中已經被移動,或者其狀態需要更新,讀屏障會自動將引用修正為新地址或更新其標記狀態,然后才將修正后的引用返回給應用程序。
  • 效果: 在并發對象移動的情況下,確保應用程序總是訪問到對象最新、正確的地址,從而避免了因對象移動導致的任何不一致,也就間接解決了標記階段的正確性。
  • 采用者: ZGC (染色指針),Shenandoah GC (Brooks Pointer)。

5. 各GC收集器中的三色標記應用

  • CMS GC (Concurrent Mark-Sweep):
    • 標記算法: 基于三色標記。
    • 屏障: 主要使用增量更新(寫屏障)。在并發標記階段,如果黑色對象引用了白色對象,CMS會通過寫屏障將黑色對象置灰,以便重新掃描。這會導致浮動垃圾,但避免了漏標。
    • 暫停: 初始標記和最終標記階段需要STW。
  • G1 GC (Garbage-First):
    • 標記算法: 基于三色標記。
    • 屏障: 使用SATB(前寫屏障)。G1會在并發標記開始時創建堆的邏輯快照,并發標記過程中引用的刪除會被記錄下來。最終標記時,會處理這些記錄。SATB能非常高效地避免漏標,但會產生更多的浮動垃圾
    • 暫停: 初始標記(通常與Young GC綁定)、最終標記(Remark)、混合GC(Mixed GC)階段需要STW。
  • ZGC (The Z Garbage Collector):
    • 標記算法: 內部仍基于三色標記思想(通過染色指針的Marked0/Marked1位表示)。
    • 屏障: 核心是讀屏障染色指針。讀屏障會在應用程序讀取引用時檢查染色指針的狀態,如果對象正在被移動或標記狀態需要更新,屏障會直接修正引用。
    • 暫停: 初始標記、最終標記和轉移開始這幾個STW階段的停頓時間與堆大小無關,極短(亞毫秒級)。
  • Shenandoah GC:
    • 標記算法: 內部基于三色標記。
    • 屏障: 核心是讀屏障Brooks Pointer(轉發指針)。讀屏障在讀取引用時,通過Brooks Pointer找到對象的最新地址。
    • 暫停: 初始標記和最終標記這幾個STW階段的停頓時間與堆大小無關,極短(亞毫秒級)。

6. 總結

三色標記算法是理解現代垃圾回收器并發機制的基石。它通過將對象劃分為白、灰、黑三種顏色,清晰地定義了GC的標記過程。然而,在并發GC中,由于應用程序線程對對象圖的修改,可能導致漏標(最危險)或錯標(浮動垃圾)。各種屏障機制(寫屏障的增量更新/SATB、讀屏障)被發明出來,以保證并發GC過程中的引用修改不會導致漏標,從而確保GC的正確性,并盡可能地減少STW時間。

不同GC收集器選擇不同的屏障機制和并發策略,以在吞吐量、停頓時間和內存/CPU開銷之間取得平衡。理解這些機制有助于我們更好地診斷GC問題和進行性能調優。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/97710.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/97710.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/97710.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

優化神經網絡模型以提升R2值至0.99的全面方案

優化神經網絡模型以提升R值至0.99的全面方案 1. 問題分析與背景 在深度學習項目中,提升模型的R(決定系數)值至0.99是一個具有挑戰性的目標,特別是在處理復雜的時間序列數據時。我們的現有模型結合了LSTM層、自注意力機制和MLP處理…

pgNow:一款免費的PostgreSQL監控與性能診斷工具

pgNow 是一款免費的桌面工具,可以為 PostgreSQL 數據庫提供快速集中的監控與性能診斷。 pgNow 不依賴代理,無需任何配置,可以幫助開發者或數據庫管理員(DBA)直觀地查看數據庫的統計信息和關鍵性能指標。 功能特性 跨平…

深入理解棧與隊列——從原理理解到實戰應用

目錄 一、引言 二、棧(Stack) 2.1 棧的基本概念 2.2 棧的使用 2.3 棧的模擬實現 2.4 棧的實戰應用 2.4.1 括號匹配 2.4.2 逆波蘭表達式求值 2.4.3 出棧入棧次序匹配 2.4.4 最小棧 三、隊列(Queue) 3.1 隊列的基本概念 …

用html5寫王者榮耀之王者墳墓的游戲2deepseek版

我將為您創建一個王者榮耀英雄墳墓游戲的提詞器HTML頁面。這個工具將幫助游戲主播或玩家在游戲中快速查看英雄技能、連招順序等信息。設計思路 創建英雄選擇界面實現提詞器顯示區域,可自定義文本內容添加字體大小、滾動速度控制設計符合王者榮耀風格的UI下面是…

輕閱讀:一鍵解決瀏覽器無法預覽Office文檔的實用方案

在日常辦公中,通過瀏覽器直接打開Word、Excel或PPT等文檔時,常遇到“需下載后用本地軟件打開”的困擾,不僅流程繁瑣,還面臨格式兼容、設備存儲不足等問題。輕閱讀(QingYueDu)作為一款輕量級文件在線預覽工具…

鴻蒙開發實戰項目(六十七):常見組件和容器低代碼開發示例(ArkTS)

本文詳細代碼需訂閱下面專欄獲取(訂閱后私信郵箱+項目名): https://blog.csdn.net/m0_68036862/category_12333038.html 目錄 介紹 環境搭建 代碼結構解讀 創建低代碼工程 低代碼設計界面布局 實現數據動態渲染 手動創建低代碼頁面 介紹 本篇Codelab是基于ArkTS語言的…

MySQL學習筆記04-DML-數據的增刪改

新增數據--insert樣例代碼-- DML : 數據操作語言 -- DML : 插入數據 - insert -- 1. 為 emp 表的 username, password, name, gender, phone 字段插入值 insert into emp (username,password,name,gender,phone) values(fei,123456,張飛,1,13888888888);-- 2. 為 emp 表的 所有…

拼多多返利app的服務網格(Service Mesh)實踐:Istio在導購系統中的應用

拼多多返利app的服務網格(Service Mesh)實踐:Istio在導購系統中的應用 大家好,我是阿可,微賺淘客系統及省賺客APP創始人,是個冬天不穿秋褲,天冷也要風度的程序猿! 在拼多多返利app的…

【RabbitMQ】高級特性:持久性·發送方確認·重試機制·TTL·死信隊列·延遲隊列·事務·消息分發

RabbitMQ的高級特性還包括我的上篇博客 【RabbitMQ】-----詳解RabbitMQ高級特性之消息確認機制-CSDN博客 目錄 RabbitMQ高級特性之持久性 持久性 交換機持久化 隊列持久化消息持久化 RabbitMQ高級特性之發送方確認機制 發送方確認 添加配置 常量類 聲明隊列和交換機…

鴻蒙Next ArkWeb網頁多媒體開發實戰:從基礎到高級應用

解鎖鴻蒙ArkWeb的強大多媒體能力,讓網頁視頻音頻體驗媲美原生應用在日常應用開發中,我們經常需要在應用中嵌入網頁并展示其中的多媒體內容。鴻蒙HarmonyOS Next的ArkWeb組件提供了強大的網頁渲染能力,尤其對網頁中的多媒體元素有出色的支持。…

06. Linux進程概念 1

Linux進程概念 馮諾依曼體系 馮諾依曼體系結構(Von Neumann Architecture)是現代計算機設計的奠基石,由數學家約翰馮諾依曼于1945年提出。這一架構徹底改變了早期計算機“硬件即程序”的設計方式,使得計算機可以靈活地運行不同程序…

HTTP標頭全解析:保護你的Web應用!

在網絡攻擊頻發的時代,你的Web應用是否像一座沒有城墻的城堡,任由XSS、點擊劫持和中間人攻擊入侵?HTTP標頭,這些看似不起眼的響應頭,其實是Web安全的隱形守護者。想象一個電商網站,用戶數據被竊取&#xff…

rt-linux下__slab_alloc里的另外一處可能睡眠的邏輯

一、背景 在之前的博客 tasklet上下文內存分配觸發might_alloc檢查及同步回收調用鏈 里,我們講了一處內存分配時會引起睡眠的調用鏈(這個引起睡眠的這個調用鏈它是在普通linux里也是存在的)。這篇博客里,我們講一處內存分配路徑下…

基于STM32F103C8T6的智能環境監測系統:DHT11溫濕度檢測與OLED顯示實現

引言 你是否曾想實時握身邊環境的溫濕度變化?無論是居家種植需要精準調控環境,還是實驗室存放敏感材料需監控條件,亦或是智能座艙場景下的環境感知,智能環境監測系統正成為連接物理世界與數字管理的重要橋梁。而在眾多嵌入式開發…

動態規劃在子數組/子串問題

目錄 一、最大子數組和(LeetCode 53) 二、環形子數組的最大和(LeetCode 918) 三、乘積最大子數組(LeetCode 152) 四、乘積為正數的最長子數組長度(LeetCode 1567) 五、等差數列…

微信小程序開發筆記(01_小程序基礎與配置文件)

ZZHow(ZZHow1024) 參考課程: 【尚硅谷微信小程序開發教程】 [https://www.bilibili.com/video/BV1LF4m1E7kB] 009_文件和目錄結構介紹新建頁面與調試基礎庫 一個完整的小程序項目分為兩個部分:主體文件、頁面文件 主體文件又稱全局文件,能夠作用于整…

NLP Subword 之 BPE(Byte Pair Encoding) 算法原理

本文將介紹以下內容: 1. BPE 算法核心原理2. BPE 算法流程3. BPE 算法源碼實現DemoBPE最早是一種數據壓縮算法,由Sennrich等人于2015年引入到NLP領域并很快得到推廣。該算法簡單有效,因而目前它是最流行的方法。GPT-2和RoBERTa使用的Subword算…

CSS 偽類選擇器

偽類選擇器(pseudo-class selector)是一種用于選擇HTML元素特定狀態或特征的關鍵字,它允許開發者基于文檔樹之外的信息(如用戶交互、元素位置或狀態變化)來選擇元素并應用樣式。偽類選擇器以冒號(:)開頭,附…

Electron 新特性:2025 版本更新解讀

引言:Electron 新特性在 2025 版本更新中的解讀核心價值與必要性 在 Electron 框架的持續演進中,新特性的引入是推動桌面開發創新的核心動力,特別是 2025 年的版本更新,更是 Electron 項目從成熟生態到前沿技術的躍進之鑰。它不僅…

MyBatis從入門到面試:掌握持久層框架的精髓

MyBatis從入門到面試:掌握持久層框架的精髓 前言 在Java企業級應用開發中,持久層框架的選擇至關重要。MyBatis作為一款優秀的半自動化ORM框架,以其靈活的SQL定制能力和良好的性能表現,成為了眾多開發者的首選。本文將帶你從MyBa…