亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java之CMS和G1垃圾回收過程的異同說明

 更新時間:2024年09月21日 09:41:15   作者:SnailMann  
CMS垃圾回收器主要基于并發(fā)-清理算法,目的是減少停頓時間,通過四個主要階段進(jìn)行垃圾回收:初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記和并發(fā)清理,G1垃圾回收器采用標(biāo)記-整理算法,是JDK9后的默認(rèn)垃圾收集器,設(shè)計為全功能全代收集器

CMS 和 G1 垃圾回收過程的異同

垃圾回收

CMS 垃圾回收

CMS 垃圾收集器是基于并發(fā)-清理(Mark-Sweep) 算法,以獲取最短停頓時間為目標(biāo)的垃圾收集器,是 JVM 第一款真正意義上的并發(fā)收集器。CMS 垃圾回收整體分為 4 個過程

初始標(biāo)記(CMS initial mark)

  • STW, 暫停所有業(yè)務(wù)線程
  • 標(biāo)記 GC Roots 的直接關(guān)聯(lián)對象
  • 能找到的第一個對象,速度很快

并發(fā)標(biāo)記 (CMS concurrent mark)

  • 并發(fā)標(biāo)記是基于初始標(biāo)記得知的 GC Roots 的直接關(guān)聯(lián)對象開始遍歷整個對象圖的過程,這個過程耗時較長,但無需 STW, GC 線程與業(yè)務(wù)線程同時進(jìn)行,會造成浮動垃圾和漏標(biāo)問題
  • 過程中,GC 線程會記錄黑色對象引用白色對象的記錄,并用于重新標(biāo)記階段的二次檢查

重新標(biāo)記 (CMS remark)

  • 基于并發(fā)標(biāo)記產(chǎn)生的漏標(biāo)問題,開啟 STW, 使用增量更新算法,將并發(fā)標(biāo)記期間出現(xiàn)的漏標(biāo)現(xiàn)象進(jìn)行二次標(biāo)記。即黑色對象被置為灰色,GC 線程重新掃描這些對象的引用路徑,避免漏標(biāo)
  • 這個階段的停頓會比初始標(biāo)記要長

并發(fā)清理 (CMS concurrent sweep)

  • GC 線程開始對白色對象
  • 即無引用的垃圾進(jìn)行回收

CMS 會造成的問題

  • 多標(biāo)問題,產(chǎn)生浮動垃圾
  • 漏標(biāo)問題, 產(chǎn)生 BUG

G1 垃圾回收

G1 垃圾收集器整體上采用標(biāo)記-整理算法,細(xì)節(jié)上是一種復(fù)制算法,作為一種全功能全代的垃圾收集器,是 JDK9 之后的默認(rèn)垃圾收集器,用于替代 CMS。垃圾回收的主要過程跟 CMS 一樣,主要也是 4 個階段

初始標(biāo)記 (Inital Marking)

  • STW, 僅標(biāo)記 GC Roots 能直接關(guān)聯(lián)到的對象,耗時很短,跟 CMS 一樣

并發(fā)標(biāo)記 (Concurrent Marking)

  • 從 GC Roots 直接關(guān)聯(lián)對象開始可達(dá)性分析,掃描對象圖,耗時很長,并發(fā)執(zhí)行。
  • 同理會造成浮動垃圾和漏標(biāo)問題;為了避免漏標(biāo)問題,采用 SATB 原始快照記錄下在并發(fā)時有引用變動的對象。即白色對象從灰色對象的引用中斷開

最終標(biāo)記 (Final Marking)

  • STW, 用于處理并發(fā)標(biāo)記階段留下的少量 SATB 記錄。
  • 將斷開的白色對象置為灰色,讓 GC 線程重新掃描這些對象

篩選回收 (Live Data Counting And Evacuation)

  • 負(fù)責(zé)更新 Region 的統(tǒng)計數(shù)據(jù),對各個 Region 的回收價值和成本進(jìn)行排序。然后根據(jù)用戶預(yù)期停頓時間,自由任意選擇多個 Region 構(gòu)成回收集(CSet)
  • STW, GC 線程并行將需要回收的 CSet 中的存活對象復(fù)制到空閑狀態(tài)的 Region 中

注意解釋

  • 這里對篩選回收其實是一種通用簡單的解釋方案,實際上并不是這樣;老年代回收分為兩個階段標(biāo)記,一,并發(fā)標(biāo)記階段。二,垃圾回收階段。而并發(fā)標(biāo)記階段分為 4 個階段(初始標(biāo)記,并發(fā)標(biāo)記,重標(biāo)記,清理階段)。本文將并發(fā)標(biāo)記階段的清理子階段和垃圾回收階段合并稱之為篩選回收
  • 實際上清理子階段并不處理垃圾回收的事情,僅僅統(tǒng)計 region 排序,得出 Cset, 不過依然要 STW; 而垃圾回收階段才真正進(jìn)行存活對象的拷貝和垃圾回收。但每次垃圾回收都是在新的一輪 YGC 開始才會發(fā)生。即不管是 YGC 還是 Mixed GC,最終只會得到要清理的 CSet, 在新的一輪 CG 來臨時,才會去清理,即延遲清理。雖然我們不知道有什么好處

CMS, G1 針對三色標(biāo)記漏標(biāo)的策略

不管是 CMS 還是 G1, 都是采用三色標(biāo)記算法來處理并發(fā)垃圾回收的問題,但對其可能會造成的漏標(biāo)行為,卻采用了不同的行為

增量更新策略

  • 在并發(fā)標(biāo)記階段,記錄由黑色對象引用白色對象的變動
  • 在重新標(biāo)記階段,STW, 對黑色對象置灰,重新掃描灰色對象以及其引用路徑

我的理解中,增量更新策略就類似在黑色對象引用白色對象的插入屏障中,記錄這樣一個信息,交給重新標(biāo)記階段去處理

SATB (snapshot-at-beginning)策略

  • 在并發(fā)標(biāo)記階段,記錄從灰色對象中斷開的白色對象的變動,說白了就是將原有引用信息記錄下來,后續(xù)處理
  • 在最終標(biāo)記階段,STW 處理這些變化,將斷開的白色對象置為灰色,最終等待 GC 線程掃描

我的理解是,SATB 同樣是利用寫屏障,只不過利用的是刪除屏障,即在白色對象斷開的時候,記錄下原有的指向信息,因為它認(rèn)為在一開始所記錄的所有對象都要被掃描。同理交給最終標(biāo)記階段去處理

Golang 策略

  • 插入屏障/ 刪除屏障
  • 混合寫屏障

G1 有什么優(yōu)勢?為什么可以替換 CMS ?

G1 的優(yōu)勢

  • 具有可預(yù)測的停頓時間模型,支持用戶設(shè)置預(yù)期的停頓時長;即 G1 可以盡可能讓停頓時間在用戶希望的范圍浮動
  • 全新設(shè)計,全年代回收,簡單高效
  • 相較 CMS ,不會產(chǎn)生空間碎片

G1 的缺點(diǎn)

  • 相較 CMS 需要更多的系統(tǒng)內(nèi)存占用,比如占用總空間的 10 ~ 20 %

替換場景

  • 在 CMS 上,假設(shè)在秒殺場景,一瞬間來了大量請求,如果年輕代設(shè)置的過小,會導(dǎo)致 Survice 區(qū)因為有對象存活,導(dǎo)致新對象無法進(jìn)入年輕代,而被擔(dān)保進(jìn)老年代。逐漸積累,會導(dǎo)致 Full GC。尤其在高并發(fā)場景,這非常容易導(dǎo)致頻繁的 Full GC, 這也就會造成嚴(yán)重的卡頓
  • 在 CMS 上,解決方式也很簡單,因為秒殺瞬間,大部分對象都是一會就死亡的,基本不會是老年代對象。所以我們只需要縮小老年代大小,增加年輕代大小就可以解決這個問題
  • 在 G1 上,就更容易解決了, 因為年輕代大小會根據(jù)每次的 YGC 進(jìn)行自動的調(diào)節(jié)。我們不需要主動設(shè)置,G1 可以自行的解決這個問題,自行選擇合適的年輕代和老年代比例

問題

CMS 初始標(biāo)記為什么需要 STW ?

  • 如果初始標(biāo)記不 STW , 在程序運(yùn)行的過程中,會有不斷的局部變量出現(xiàn),這樣我們就不知道要標(biāo)記到什么時候才算結(jié)束了
  • 同時初始標(biāo)記耗時很短,所以即時 STW 也不會影響什么

G1 篩選回收為什么需要 STW ?

  • 首先篩選回收階段,我們需要分為兩個部分,一部分是進(jìn)行 Region 垃圾信息等統(tǒng)計,并根據(jù)排序選擇指定的 CSet, 這部分需要 STW, 避免并發(fā)帶來的麻煩。
  • 另一部分就是垃圾清理, 因為涉及到了存活對象的復(fù)制,將對象從一塊區(qū)域復(fù)制到另一塊區(qū)域,如果沒有 STW, 可能會導(dǎo)致對象覆蓋的問題

在并發(fā)標(biāo)記階段,如果沒有 STW, 新加入的對象要怎么處理?

新加入的對象有那么幾種可能的情況

  • 新加入對象是GC Roots 直接關(guān)聯(lián)對象
  • 新加入對象被黑色對象引用了
  • 新加入對象被白色或灰色對象引用了

假設(shè)新加入對象分配為白色對象,那么就存在幾個問題

  • 如果是 GC Roots 直接關(guān)聯(lián)對象,因為已經(jīng)錯過了初始標(biāo)記,所以會導(dǎo)致新對象被認(rèn)為是垃圾,而被回收掉
  • 如果被黑色對象引用,且沒有其他引用路徑,這就造成了漏標(biāo)問題,依舊會被當(dāng)做是垃圾回收掉
  • 如果是白色或灰色引用,那么問題不大

不管怎么說,依然會存在新加入對象被當(dāng)做垃圾回收掉的問題,所以新對象直接分配為白色對象是有問題的,我們要怎么處理才合理呢?

在不同的語言,不同的垃圾收集器,我猜測應(yīng)該由不同的處理方式,這里可以列舉一下

  • Go 1.8 中,三色標(biāo)記 + 混合寫屏障策略下,新加入的對象都標(biāo)記為灰色。所以新對象肯定會被 GC 線程掃描。優(yōu)點(diǎn)就是避免漏標(biāo),缺點(diǎn)就是可能多標(biāo),造成浮動垃圾
  • 同理,CMS 或 G1 我猜測也是使用了類似方案

G1 到底使用什么垃圾回收算法?

網(wǎng)上通常說 G1 采用的是標(biāo)記-整理算法,整體上也可以這么去理解

- 整體標(biāo)記-整理,細(xì)節(jié)復(fù)制算法

- G1 會將需要回收的 region 中活躍的對象拷貝到空閑分區(qū),然后將回收 region 進(jìn)行清理,再歸類為空閑分區(qū),這一個過程像是標(biāo)記整理,也像復(fù)制算法

  • G1 只提供有 YGC 和 Mixed GC 選項, 如果Mixed GC實在無法跟上程序分配內(nèi)存的速度,導(dǎo)致老年代填滿無法繼續(xù)進(jìn)行 Mixed GC,就會使用Serial Old GC(Full GC)來收集整個GC heap。所以我們可以知道,G1是不提供Full GC的, 且要避免 Full GC
  • JDK10 之間只有串行 Full GC, 11 后則由并行 Full GC 了

G1 GC 與垃圾回收過程怎么混合理解?

G1 的并發(fā)標(biāo)記階段僅僅針對與老年代對象的分析,即我們在上面描述的垃圾回收階段是針對 G1 老年代回收的,新生代回收相比以上更加的簡單。全程 STW, GC 線程并行回收新生代對象

實際上 Mixed GC 就包含了 YGC 的整個過程,即如果發(fā)生了 Mixed GC, 那么之前必然發(fā)生了 YGC。我們可以簡單的理解 YGC 的過程只有兩個階段 (初始標(biāo)記,篩選回收)。而在初始標(biāo)記過后,當(dāng)堆內(nèi)存的占用到達(dá)內(nèi)存可用總量的 45% (可設(shè)置),就會觸發(fā)并發(fā)標(biāo)記階, 此時就代表從 YGC 進(jìn)階到 Mixed GC, 之后就走正常的流程了

Mixed GC 的開始,基于 G1 YGC 的完成,并發(fā)標(biāo)記過程由并發(fā)標(biāo)記線程從 Survivor 區(qū)或老年代的 RSet 記錄的活躍對象作為根并開始標(biāo)記

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MyBatis?超詳細(xì)講解動態(tài)SQL的實現(xiàn)

    MyBatis?超詳細(xì)講解動態(tài)SQL的實現(xiàn)

    動態(tài)?SQL?是?MyBatis?的強(qiáng)大特性之一。如果你使用過?JDBC?或其它類似的框架,你應(yīng)該能理解根據(jù)不同條件拼接?SQL?語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態(tài)?SQL,可以徹底擺脫這種痛苦
    2022-03-03
  • 詳談jvm線程??臻g內(nèi)存分配位置

    詳談jvm線程??臻g內(nèi)存分配位置

    這篇文章主要介紹了jvm線程棧空間內(nèi)存分配位置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Spring Boot統(tǒng)一返回體的踩坑記錄

    Spring Boot統(tǒng)一返回體的踩坑記錄

    這篇文章主要給大家介紹了關(guān)于Spring Boot統(tǒng)一返回體踩坑的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Java實現(xiàn)簡單點(diǎn)餐系統(tǒng)

    Java實現(xiàn)簡單點(diǎn)餐系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡單點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Spring中@PostConstruct注解的使用講解

    Spring中@PostConstruct注解的使用講解

    這篇文章主要介紹了Spring中@PostConstruct注解的使用講解,被@PostConstruct修飾的方法會在服務(wù)器加載Servlet的時候運(yùn)行,并且只會被服務(wù)器執(zhí)行一次,PostConstruct在構(gòu)造函數(shù)之后執(zhí)行,init()方法之前執(zhí)行,PreDestroy()方法在destroy()方法之后執(zhí)行,需要的朋友可以參考下
    2023-11-11
  • MyBatis實現(xiàn)遞歸查詢的方法詳解

    MyBatis實現(xiàn)遞歸查詢的方法詳解

    在項目開發(fā)過程中,往往會遇到多級菜單、分類等多層級結(jié)構(gòu)數(shù)據(jù)的查詢。本文就來為大家講講MyBatis實現(xiàn)遞歸查詢的方法,感興趣的可以動手嘗試一下
    2022-08-08
  • java抓取網(wǎng)頁數(shù)據(jù)獲取網(wǎng)頁中所有的鏈接實例分享

    java抓取網(wǎng)頁數(shù)據(jù)獲取網(wǎng)頁中所有的鏈接實例分享

    java抓取網(wǎng)頁數(shù)據(jù)獲取網(wǎng)頁中所有的鏈接實例分享,使用方法,只要實例化HtmlParser時傳入網(wǎng)頁地址就可以了
    2013-12-12
  • IDEA反編譯jar,查看源碼方式

    IDEA反編譯jar,查看源碼方式

    該篇文章總結(jié)了查看Java本地jar包注釋的幾種方法,包括使用快捷鍵CTRL+q和在設(shè)置中設(shè)置自動浮現(xiàn)注釋
    2024-11-11
  • 解析MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件

    解析MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件

    在項目中用到了MapStruct,對其可以轉(zhuǎn)換JavaBean特別好奇,今天小編給大家分享一個demo給大家講解MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件,感興趣的朋友一起看看吧
    2021-09-09
  • Java開發(fā)環(huán)境jdk 1.8安裝配置方法(Win7 64位系統(tǒng)/windows server 2008)

    Java開發(fā)環(huán)境jdk 1.8安裝配置方法(Win7 64位系統(tǒng)/windows server 2008)

    這篇文章主要介紹了Java開發(fā)環(huán)境配置方法(Win7 64位系統(tǒng)/windows server 2008),需要的朋友可以參考下
    2016-10-10

最新評論