成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

G1 面向服務端(多CPU)應用的垃圾回收器

開發 前端
垃圾回收器可以說事Java的基石之一,垃圾回收器的實現充滿了大量的實現細節,對于一些優化十分具有參考價值。

總則:首先收集盡可能多的垃圾(Garbage First)

一定程度上,可以理解為 是CMS在全局不分區的一種改進。G1并不會等內存耗盡(串行、并行)或者快耗盡(CMS)的時候開始垃圾收集,而是在內部采用了啟發式算法,在老年代找出具有高收集收益的分區進行收集。

特點:

并發與并行:G1能充分的利用多CPU,多核環境下的硬件優勢,使用多個CPU來縮短STW停頓時間。部分收集器需要停頓Java線程來執行GC動作,G1收集器仍然可以通過并發的方式讓java程序繼續運行。

分代收集:G1可以獨自管理整個Java堆,只進行邏輯上的年輕代與老年代的區別。采用不同的方式去處理新創建的對象和已經存活了一段時間的對象和已經熬過多次GC的舊對象以獲得更好的收集效果。

空間整合:G1運作期間不會產生空間鎖片,收集后能提供規整可用的內存。G 1將內存劃分為一個個相等大小的內存分區,回收時則以分區為單位進行回收,存活的對象復制到另一個空閑分區中。由于都是以相等大小的分區為單位進行操作,因此G1天然就是一種壓縮方案(局部壓縮);

可預測的停頓:G1除了追求低停頓外,還能建立可以預測停頓時間的模型。能讓使用者明確指定在一個長度為M毫秒的時間段,消耗在垃圾回收上的時間不超過N毫秒。可以根據用戶設置的暫停時間目標自動調整年輕代和總堆大小,暫停目標越短年輕代空間越小、總空間就越大;

G1模型

內存模型

分區(Region)

G1采用了內存分區的概念,將整堆分為若干大小相等的區域逐步使用;G1僅要求對象邏輯上連續。區域也不會跟代進行綁定,可以切換代所屬。可以通過 -XX:G1HeapRegionSize=n設置整堆的大小(1-32mb,2^n),默認將整堆劃分為2048個分區。說白了就是-Xms /2048 ,如果這個值小于1,則取值為1,大于32則取值32;其它值則取與2,4,8,16相近的。

卡片(card)

每個分組內部劃分多個大小為512byte的卡片。同時G1 GC為每個區間設置了一個全局內存塊表(Global Card Table)來幫助維護所有的堆內存塊。內存回收是對卡片進行處理的。

堆 (head)

代表整體空間總大小。可用-Xms/-Xmx來指定。在發生年輕代收集或混合收集的時候,會通過計算GC與應用的耗費時間比,自動調整堆空間。GC頻率高則增大堆空間,GC占用時間高則減小堆空間。GC時間與應用耗時比默認為9。空間不足時會先嘗試擴容,失敗則進行Full GC。

分代模型

分代的分割

更關心最近被分配的對象,避免對長生命周期的對象進行改動。借鑒了分代思想,將內存區邏輯區分為年輕代、幸存代、老年代。但是JVM會動態的調整空閑區間到年輕代空間。

年輕代會在初始空間(-XX:G1NewSizePercent 默認 5%)到最大空間(-XX:G1MaxNewSizePercent默認60%) 之間動態變化,且由參數目標暫停時間(-XX:MaxGCPauseMillis默認200ms)

本地分配緩沖 Local allocation buffer (Lab)

由于是分區的內存,所以可以每個線程領取一部分內存使用。這樣領取后的內存與GC所進行任務的內存都是獨立進行的,從而減少同步時間,提高GC時的效率。稱這種線程領取后的分區稱之為本地分配緩存。

分區模型

G1對內存的分配是以“分區(Region)”為單位,針對區內對“對象”的分配是以“卡片(Card)”為單位。

巨型對象區域 (Humongous Region)

大于了分區大小一半以上的對象成為巨型對象。由于巨型對象的移動成本很高,甚至分區無法容納對象,所以線程并不會直接在TLAB中創建對象。針對巨型對象,會直接分配在老年代的連續空間中,所占用的連續空間叫做“巨型分區(Humongous Region)”。優化: 巨型對象如果沒有指向巨型對象,直接會在年輕代收集周期中被回收。

巨型對象會獨占一個、或多個物理連續分區,其中第一個分區被標記為開始巨型(StartsHumongous),相鄰連續分區被標記為連續巨型(ContinuesHumongous)。由于無法享受Lab帶來的優化,并且確定一片連續的內存空間需要掃描整堆,因此確定巨型對象開始位置的成本非常高,如果可以,應用程序應避免生成巨型對象。

已記憶集合 Remember Set (RSet)

Serial 和Parllel GC的時候是掃描整堆來確認可達性。G1 通過為每個分區建立一個已記憶集合 (RSet)記錄引用分區內對象的卡片索引(反向索引,誰引用了我),當要回收該分區時,通過掃描分區的RSet,來確定引用本分區內的對象是否存活,進而確定本分區內的對象存活情況。

RSet空了,說明這個Region中的中的對象已經沒有被其他對象引用了。

兩種場景下依賴Rset加速(由于年輕代會被完整回收,同時因為寫屏障性能消耗,所以不記錄年輕代飲用)。

  • 老年代引用老年代對象,Rset保存在老年代中
  • 老年代引用年輕代對象,Rset保存在年輕代中

Per Region Table (PRT)

RSet通過PRT記錄分區的引用情況。當一個指針引用到Rset中的一個區間時(圖右上角),包含該指針的堆塊就會被PRT標記。PRT需要內存空間來存儲這些引用關系,根據引用的數量,PRT有三種的記錄引用的模式,會根據調用次數轉變: 稀疏(hash)->細粒度->粗粒度。

稀疏表:通過哈希表來存儲,key是region index,value是card數組

細粒度PerRegionTable:當稀疏表指定region的card數量超過閾值時,則在細粒度PRT中創建一個對應的PerRegionTable對象。一個Region地址鏈表,維護當前Region中所有card對應的一個BitMap集合。

粗粒度位圖:當細粒度PRT size超過閾值時,所有region 形成一個 bitMap。如果有region 對當前 Region 有指針指向,就設置其對應的bit 為1

CSet

收集集合(CSet)代表每次GC暫停時回收的一系列目標分區。在收集暫停中,CSet Region都會被釋放,存活的對象會被分配到空閑分區中。G1的收集都是根據CSet進行操作的,年輕代收集與混合收集沒有明顯的不同,最大的區別在于兩種收集的觸發條件。

年輕代收集集合:

當年輕代空間增長到Eden已經滿了的時候,便會觸發一次STW式的年輕代收集。Eden分區存活的對象將被拷貝到Survivor分區;原有Survivor分區存活的對象,將根據任期閾值(tenuring threshold)分別晉升到PLAB中、新的survivor分區和老年代分區。而原有的年輕代分區將被整體回收掉。

混合收集集合:

老年代的空間被逐漸填充。當老年代占用空間超過整堆比IHOP閾值

-XX:InitiatingHeapOccupancyPercent(默認45%)時,G1就會啟動一次混合垃圾收集周期。為了減小暫停目標,混合收集會分批次,與用戶線程交替執行,每次STW的混合收集與年輕代收集過程相類似。

G1的活動周期

工作流程:

RSet的維護

G1通過維護RSet來記錄對象分區之間的引用,避免全量掃堆。維護RSet通過兩個方面:

寫屏障(Write Barrier)

并發優化線程(Concurrence Refinement Threads)

寫屏障

屏障指在原生代碼片段中,當某些語句被執行時,柵欄代碼也會被執行(類似aop)。G1主要在賦值語句中,使用寫前柵欄(Pre-Write Barrrier)和寫后柵欄(Post-Write Barrrier)。注意: 寫柵欄的指令序列開銷非常昂貴,應用吞吐量也會根據柵欄復雜度而降低。

寫前屏障: 在進行等式賦值前,等式左側原先的引用就會失去一個引用,所以jvm就需要在語句執行前記錄喪失的引用對象。(并不是立即執行,是后續批量執行,使用SATB方法)

寫后屏障: 賦值等式執行后,右側的引用多了一個引用,需要確實否是需要增加引用,JVM也不會立即處理,會先進行記錄,然后會在后續進行批量處理(并發優化線程)。

SATB + RSet 解決了什么問題?

主要是為了解決并發標記過程中,出現的漏標,誤標等問題。

起始快照算法(Snapshot at the beginning (SATB))-寫前屏障處理

G1 SATB和Incremental Update算法的理解

SATB是一種增量式完全并發標記算法,針對并發標記階段,適用于G1的分塊堆結構。

SATB 算法認為開始標記的都認為是活的對象,SATB會創建一個對象圖,相當于堆的邏輯快照。所以對象可按圖結構遍歷(用RSet可以加速)。當發生已掃描對象引用未掃描對象時(黑色引用白色),通過write barrier寫屏障技術,會把B到D 的引用推到gc 遍歷執行的堆棧上,這樣在后續會繼續針對D進行掃描。

Snapshot at the beginning,可以理解為,在進行掃描之前,將整個對象引用關系都認為是 存活的節點進行掃描,如果在掃描過程中把B = null,這是D其實已經是垃圾了,但是在后續流程中仍然會處理D并標記為黑色。D在本輪本該清除,但是會暫時保留,在remark階段處理。

每個線程有一個256條記錄的SATB緩存區,當滿了之后會將數據加入到全局列表中中并重新申請新的一批256緩存。還會定期檢查和處理全局緩沖區列表的記錄,然后根據標記位圖分片的標記位,掃描引用字段來更新RSet。此過程又稱為并發標記/SATB寫前柵欄。

并發優化線程(Concurrence Refinement Threads)- 寫后屏障處理

寫后屏障(需要2個額外指令)會更新一個Card Table Type結構來跟蹤代間引用。觸發寫屏障時,會過濾是否為本分區的對象,如果發生跨區應用更新,則將更新對象的卡片加入到緩沖(新日志緩沖或者臟卡片)。一旦日志緩沖區用盡,則分配一個新的日志緩沖區,并將原來的緩沖區加入全局列表中。

并發優化線程會一直活躍,當全局列表中有數據就會處理來更新RSet。如果處理不過來,就會讓更多線程來處理全局表;如果還處理不過來,會暫停應用線程來處理全局列表。(對象變更過于頻繁)

并發標記周期

并發標記周期(Concurrent Marking Cycle)需要會為混合收集周期識別垃圾最多的老年代分區。整個周期完成根標記、識別可能存活對象、計算分區活躍從而確定GC效率等級。

觸發條件: 達到IHOP閾值(

-XX:InitiatingHeapOccupancyPercent 老年代整堆比,默認45%),

步驟(STW):

  • 初始標記(Initial Mark)
  • 根分區掃描(Root Region Scanning)
  • 并發標記(Concurrent Marking)
  • 重新標記(Remark)
  • 清除(Cleanup)
  • 并發標記線程 (Concurrent Marking Threads)

并發標記階段,會針對分區進行數據標記,一個分區會會建立兩個位圖來記錄標記結果:Previous Bitmap、Next Bitmap。

  • Previous Bitmap為上一次的標記(已經完成標記)
  • Next Bitmap為本次的標記結果(即將進行標記)

對應的,針對標記的位置利用兩個變量記錄(TAMS: Top-At-Mark_Start)分別是:

  • Previous TAMS(PTAMS) 前一次
  • Next TAMS(NTAMS) 后一次

總的來說: 區間內的數據用兩個Bitmap兩個‘指針’進行滾動回收,當回收完畢后,區間回收。

初始標記結束后:會先將Next Bitmap設置為空,并將N TAMS設置到區間頂部。此時P TAMS仍然為上一大輪時標記的位置。

并發循環: 會對 PTAMS 到 NTAMS中間的數據進行標記,將本段標記的結果+上一次標記的結果一同更新到Next Bitmap。

一次循環結束: 將Next Bitmap 更新到 Previous Bitmap中,同時,更新 PTAMS與 NTAMS的位置。

在并發標記階段,G1根據參數(-XX:ConcGCThreads(默認GC線程數的1/4,即-XX:ParallelGCThreads/4))分配線程,每個線程一次流程只進行一個分區的掃描。

并發標記循環流程 (Concurrent Marking Cycle)

并發循環的流程為:初始標記、根分區掃描、并發標記、重新標記、清除階段。

初始標記(Initial Mark):

獨占,會觸發STW,然后標記GC ROOT可達的所有對象。

當IHOP觸發閾值的時候,G1并不會立即開啟循環,而是等待下一次年輕代收集(同樣需要STW),和年輕代收集一起在一次STW之間執行(借道(Piggybacking))。

在初始標記暫停中,分區的NTAMS都被設置到分區頂部Top,初始標記是并發執行,會處理所有的分區。

根分區掃描(Root Region Scanning)

當STW結束,年輕代收集和初始標記完成后。基于標記算法,拷貝到幸存者區間的區間也需要被當作根元素進行標記,同時G1會掃描這個區間,然后將幸存者區間所引用的對象進行標記。所以幸存者區間也被稱為根區間。

特別的: 因為 并發循環流程中會多次執行年輕代收集(被年輕代收集打斷),所以需要在下一次被打斷前完成。

并發標記(Concurrent Marking)

該階段和應用縣城并發執行,每個線程一次只掃描一個分區,標記出存活對象圖。在這一階段會處理Previous/Next標記位圖,掃描標記對象的引用字段。同時并發標記線程還會處理SATB的全局列表信息。

重新標記(Remark)

最后一個標記動作,會是一個獨占(STW)階段,可以并行執行。在整個階段中,會處理所有遺留的SATB日志。找出所有未被訪問的存活對象。

注意:引用處理也是重新標記階段的一部分,所有重度使用引用對象(弱引用、軟引用、虛引用、最終引用)的應用都會在引用處理上產生開銷。

清理(Cleanup)

清理結算會識別并清理完全空閑的區域(RSet中引用計數空了)并清理空閑的區域。這個階段會處理Previous/Next標記位圖、以及PTAMS/NTAMS。主要進行的操作有一下幾種:

RSet梳理(根據掃描后的結果,確認RSet各個粒度中的數據是否維護的正確)

整理堆分區,為分區確定訪問熱度,為后續確認回收收益高的分區。

識別空閑區間直接回收。

年輕代收集/混合收集周期

年輕代收集(Young Collection)

年輕代由:Eden 和 Survivor組成,當Eden分配失敗的時候會觸發,執行年輕代收集的時候會進行中斷(STW)

對象復制 Object Copy: 根據CSet 會將Eden中的存活對象復制到Survivor區間。注意:會將所有的年輕代對象(Eden和Survivor)拷貝到新的Survivor區間。

對象提升: 如果對象經歷的幸存次數達到閾值,會提升到老年代中,這個閾值經過計算配置得到。

分區調整: 收集期間,G1會計算當前年輕代需要擴容或者壓縮的總量例如:

  • 空閑區間
  • RSet大小
  • 當前最大可用年輕代
  • 當前最小可用年輕代
  • 停頓時間

信息維護: 記錄收集對象的年齡信息"Age Info",便于后續是否晉升到老年區、時候在混合收集階段進行回收。

更新RSet:會處理還沒有提交到全局列表中的本地緩沖區中的RSet更新日志。

掃描RSet: 在收集當前CSet之前,考慮到分區外的引用,必須掃描CSet分區的RSet。

釋放分區: 釋放Free CSet

混合收集周期(Mixed Collection Cycle)

當一次并發標記循環完成了之后,會開始一次混合收集周期,在周期中G1不僅收集年輕代,也同時收集老年代,而收集那些老年代,則是根據老年代中的垃圾數量確定的。

單輪的混合收集與年輕代收集無區別,但是因為老年代垃圾可能比較多,為了滿足暫停的需求,可能會連續的進行多次的混合收集。再過程中,G1會計算下一次處理的CSet集合的分區數量,是否本次收集之后需要結束周期。

Full GC

當無法申請新的空間時,會執行一次STW式的、單線程的Full GC。Full GC會對整堆做標記清除和壓縮,最后將只包含純粹的存活對象。觸發Full GC的方式:

  • 從年輕代分區拷貝存活對象時,無法找到可用的空閑分區
  • 從老年代分區轉移存活對象時,無法找到可用的空閑分區
  • 分配巨型對象時在老年代無法找到足夠的連續分區

流程簡述:

最后

垃圾回收器可以說事Java的基石之一,垃圾回收器的實現充滿了大量的實現細節,對于一些優化十分具有參考價值。


責任編輯:武曉燕 來源: 蜜糖的代碼注釋
相關推薦

2009-08-14 08:56:49

Java垃圾回收器G1

2025-05-16 08:00:00

2009-07-24 09:41:45

Java 7 G1垃圾回收器

2024-10-22 16:26:11

2009-06-02 10:18:43

Java垃圾回收器垃圾回收器Java垃圾回收

2023-11-16 08:00:56

Java11G1

2020-06-01 20:08:47

垃圾G1回收器

2009-06-18 13:59:33

Java SE 6垃圾回收器

2024-12-03 09:01:33

2021-08-10 07:00:02

Java8 G1垃圾回收器

2021-08-15 18:59:13

垃圾收集器JDK

2015-06-17 14:10:52

OracleJava 9垃圾收集器

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2022-01-20 10:34:49

JVM垃圾回收算法

2020-05-14 13:39:19

Java 垃圾回收機制

2025-01-06 08:22:41

2024-03-15 08:04:30

G1CMSJVM

2024-03-11 16:27:02

垃圾回收器JVM

2011-06-28 12:39:34

Java垃圾回收
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久久中文字幕 | 国产一区二区在线免费视频 | www.一区二区三区.com | 久久久久国产 | 日韩欧美在线视频播放 | 亚洲欧美国产视频 | 国产一区2区 | 亚洲免费视频网站 | 日本成人久久 | 超碰精品在线观看 | 97精品久久 | 日韩在线资源 | 午夜久久| 久久久免费电影 | 久久黄网 | 极品销魂美女一区二区 | 超碰精品在线观看 | 国产一区二区在线免费观看 | 日批日韩在线观看 | 国产一区二区影院 | 久久99久久久久 | 自拍中文字幕 | 国产成人精品一区二区三区视频 | 欧美黑人激情 | 国产xxxx在线 | 欧美日韩国产一区二区 | h视频免费看 | 超碰导航 | www.性色| 激情六月天 | 久久av一区二区三区 | 日韩精品视频一区二区三区 | 一本一道久久a久久精品综合蜜臀 | 91久久精品一区二区二区 | 欧美久久国产精品 | 国产一卡二卡三卡 | 一区二区三区视频在线免费观看 | 欧美最猛性xxxxx亚洲精品 | 欧美在线一区二区三区 | 九九综合 | 色花av|