JVM 并發(fā)垃圾收集算法

CMS 和 G1 算法

CMS GC (-XX:+UseConcMarkSweepGC)

并發(fā)標記掃描(Concurrent Mark Sweep挟憔,CMS)專為需要較短暫停的應(yīng)用而設(shè)計的老年代收集器链患,在應(yīng)用程序運行時需要與GC線程共享處理器資源总寒,所以需要運行在多核處理器上踩身。通常恃轩,在具有較多長生命周期數(shù)據(jù)集(老年代比較大)的應(yīng)用程序上使用篙程,從JDK 9 開始不推薦使用CMS收集器藏畅,推薦使用Garbage-First收集器

流程

每次major collection怔蚌,CMS收集器會在收集開始時暫停所有應(yīng)用程序線程巩步,叫做initial mark pause,在并發(fā)跟蹤階段結(jié)束后會再次暫停桦踊,叫做remark pause椅野,第二次暫停往往時間較長,通常與minor collection相當钞钙,兩個暫停期間都是多個線程執(zhí)行收集工作

  • 初始標記 Initial Mark :Stop-The-World鳄橘,僅僅標記GC Roots直接關(guān)聯(lián)的對象,例如線程棧和寄存器1中引用的對象芒炼,靜態(tài)對象等瘫怜,速度很快
  • 并發(fā)標記 Concurrent Mark:該階段中不需要暫停應(yīng)用程序,進行標記
  • 重新標記 Remark:再次暫停應(yīng)用程序本刽,修正因為并發(fā)標記階段應(yīng)用線程運行導(dǎo)致的對象更新鲸湃,確保所有的可達對象都被標記,時間稍長
  • 并發(fā)清除 Concurrent Sweep:執(zhí)行sweep子寓,來清除所有非可達對象所占用的內(nèi)存空間暗挑,存活的對象沒有移動,除非出現(xiàn)Concurrent Mode Failure斜友,觸發(fā)一次full GC炸裆,進行整理
  • 重置 Resetting:清除數(shù)據(jù)結(jié)構(gòu),下一次并發(fā)收集做準備
    Serial GC 和 CMS GC

    由于應(yīng)用程序線程和垃圾收集器線程在major collection期間并發(fā)運行鲜屏,因此垃圾收集器線程跟蹤的存活對象可能再收集過程結(jié)束時變得不可訪問。這些尚未回收的不可達對象被稱為浮動垃圾floating garbage。浮動垃圾的數(shù)量取決于并發(fā)收集周期的持續(xù)時間以及應(yīng)用程序的引用更新頻率(也稱為突變昙篙,mutation)。在下一次GC期間收集在當前并發(fā)收集周期結(jié)束時堆中的浮動垃圾

Concurrent Mode Failure

CMS收集器使用一個或多個與應(yīng)用程序線程同時運行的垃圾收集器線程酱吝,目標是在老年代變滿之前完成收集

在正常操作中,CMS收集器在應(yīng)用程序線程仍在運行時執(zhí)行大部分的跟蹤和清除工作土思,因此應(yīng)用程序線程只會有短暫的暫停务热。但是,如果CMS收集器無法在老年代填滿之前完成垃圾回收己儒,或者老年代中的可用空閑塊不能滿足分配需求崎岂,則所有應(yīng)用程序都將暫停,等待收集完成址愿。無法并發(fā)完成收集的情況稱為并發(fā)模式失敗该镣,表示需要調(diào)整CMS收集器參數(shù)

啟動時機

串行收集器只要老年代變滿就進行major collection,在收集過程中停止所有應(yīng)用線程
CMS收集器中并發(fā)收集必須定時開始响谓,以便GC可以在老年代填滿之前完成,否則會產(chǎn)生并發(fā)模式故障Concurrent Mode Failure省艳,導(dǎo)致更長的暫停娘纷,CMS內(nèi)部會根據(jù)歷史記錄,對老年代內(nèi)存被填滿的剩余時間以及并發(fā)的收集時間進行估計跋炕,確保在老年代用盡之前完成GC赖晶,避免并發(fā)模式故障

由于要預(yù)留空間給浮動垃圾,如果老年代的內(nèi)存占用率超過CMS初始化占用比例辐烂,同樣也會觸發(fā)CMS遏插,調(diào)整觸發(fā)CMS的老年代百分比-XX:CMSInitiatingOccupancyFraction=<N>

缺點

  • 占用更多的CPU和內(nèi)存資源
  • 無法處理Floating Garbage,需要預(yù)留一定的空間
  • 標記-清除算法纠修,不進行copy或者compact胳嘲,會產(chǎn)生碎片,連續(xù)空間不夠分配扣草,導(dǎo)致concurrent mode failure

G1 (XX:+UseG1GC)

Garbage-First(G1) 垃圾收集器適用于具有大內(nèi)存的多處理器計算機了牛,它在延遲和吞吐量之間尋找一個最佳平衡,JDK 9開始作為默認GC

特點:

  • 堆大小為10GB或更大辰妙,超過50%的Java堆被存活數(shù)據(jù)占用
  • 對象分配和晉升的比率可能會隨著時間的推移顯著變化
  • 堆中存在大量碎片
  • 可預(yù)測的暫停時間鹰祸,不超過幾百毫秒,避免長時間的垃圾收集暫停

G1是一個分代收集收集器密浑,將堆分成新生代和老年代蛙婴,算法是并行的,大部分階段是并發(fā)運行尔破,部分操作會產(chǎn)生STW暫停街图,空間回收是逐步增量的浇衬,主要通過疏散的方式進行。G1通過跟蹤先前應(yīng)用程序行為和垃圾收集暫停的信息來建立相關(guān)成本的模型台夺,從而實現(xiàn)可預(yù)測性径玖,通過模型確定暫停時間內(nèi)要完成的工作量,首先在最有價值的區(qū)域中回收空間(即區(qū)域中大部分都是垃圾颤介,這也是G1名稱的由來)

G1主要通過疏散evacuation回收空間:在選定區(qū)域內(nèi)的活動對象會被復(fù)制到新的內(nèi)存區(qū)域梳星,同時在此過程中進行整理將對象放在一起,疏散完成后滚朵,先前占用的空間就可以回收利用

G1收集器有很高的概率冤灾,滿足設(shè)定的GC停頓時間,但是并不絕對完成辕近,所以G1不是一個實時的收集器(real-time collector)

堆布局

G1將堆分區(qū)為一組大小相等的區(qū)域韵吨,每個區(qū)域都是一個連續(xù)的虛擬內(nèi)存區(qū)域,區(qū)域是內(nèi)存分配和內(nèi)存回收的單位移宅,在某一時間归粉,這些區(qū)域可以是空的,或者分配給了年輕代或老年代

區(qū)域的大小通過-XX:G1HeapRegionSize設(shè)定漏峰,默認區(qū)域大小基于堆的初始和最大大小糠悼,堆包含大約2048個區(qū)域。堆區(qū)域的大小可以在1到32 MB之間變化浅乔,但必須是2的冪次

G1堆分配

Humongous Objects

巨型對象是大于或等于半個區(qū)域大小的對象

  • 巨型對象都分配在老年代的一系列連續(xù)區(qū)域上倔喂,序列的最后一個區(qū)域中的剩余空間都不會進行分配
  • 通常,巨型對象只能在mark過程的清理Cleanup暫停期間回收靖苇,或者在無法訪問時在Full GC期間回收席噩。 但是,對于大型對象有特殊的規(guī)定贤壁,用于原始類型的數(shù)組悼枢,例如bool,各種整數(shù)和浮點值芯砸。 如果在任何類型的垃圾回收暫停中許多對象都未引用大型對象萧芙,則G1機會嘗試回收大型對象。 默認情況下啟用此行為假丧,但是您可以使用選項-XX:G1EagerReclaimHumongousObjects禁用它双揪。
  • 巨型對象的分配可能導(dǎo)致垃圾收集暫停過早發(fā)生,每次巨型對象分配時G1都會檢查初始堆占用閾值包帚,并且如果當前占用率超過該閾值渔期,則立即開始新生代收集初始標記
  • 即使在Full GC期間,這些巨型對象也不會移動,這可能會導(dǎo)致過早的Full GC疯趟,或者由于區(qū)域空間的碎片而導(dǎo)致剩余大量可用空間但是內(nèi)存不足的情況

垃圾收集周期

G1收集器在兩個階段之間交替:

  • young-only phase:期初是進行正常的年輕代收集Normal young collections拘哨,晉升對象到老年代,當老年代的占用率到達堆占用閾值信峻,進行并發(fā)收集Concurrent Start young collection倦青,步驟如下
    • 并發(fā)啟動Concurrent Start:在執(zhí)行Normal young collections的STW時進行Initial mark,然后啟動并發(fā)標記Concurrent marking盹舞,并發(fā)標記確定老年代區(qū)域中當前可到達(存活)的所有對象产镐,以便空間清理階段保留。收集標記進行過程中踢步,也會出現(xiàn)正常的代收集癣亚,即可以被年輕代的STW中斷。標記完成后還有兩個STW停頓:重新標記和清理
    • 重新標記Remark:通過STW最終確定標記获印,執(zhí)行全局引用處理和類卸載述雾,回收完全空白的區(qū)域并清理內(nèi)部數(shù)據(jù)結(jié)構(gòu)。在重新標記和清理之間兼丰,G1會并發(fā)計算所選老年代區(qū)域中能夠回收的可用空間
    • 清理Cleanup:這是標記的最后階段玻孟,STW決定是否執(zhí)行space-reclamation,如果執(zhí)行鳍征,會進行一次Prepare Mixed young collection
  • space-reclamation phase:空間回收階段由多個混合收集Mixed collections組成取募,除了處理新生代之外,老年代的空間也會進行疏散蟆技,當G1確定疏散更多的老年代區(qū)域產(chǎn)生的自由空間不值得努力時,空間回收階段結(jié)束

如果應(yīng)用程序在垃圾回收時內(nèi)存不足斗忌,則G1會像其他收集器一樣STW质礼,執(zhí)行Full GC

Collection Set:將要被GC收集的region集合,內(nèi)部的存活對象在GC期間都會被疏散(復(fù)制/移動)

young-only階段织阳,收集的區(qū)域集合(Collection Sets)僅由新生代區(qū)域組成眶蕉,G1每次在年輕代收集的末尾計算新生代的大小,在下一個階段改變唧躲。如果沒有另外約束造挽,則G1自適應(yīng)地在-XX:G1NewSizePercent-XX:G1MaxNewSizePercent之間調(diào)整大小來滿足暫停時間的要求

space-reclamation階段,G1試圖最大化回收老年代的內(nèi)存弄痹,按照回收的效率高低清理老年代區(qū)域饭入,同時通過剩余可用時間確定最終收集區(qū)域的大小,活動對象比例在-XX:G1MixedGCLiveThresholdPercent閾值之上的不進行清理肛真,-XX:G1MixedGCCountTarget設(shè)定該階段中進行Mixed垃圾收集的次數(shù)

當收集集候選區(qū)域(collection set candidate regions)中可回收的空間量小于-XX:G1HeapWastePercent設(shè)置的百分比時谐丢,結(jié)束該階段

確定啟動堆占用率

啟動堆占用百分比(Initiating Heap Occupancy Percent, IHOP)是觸發(fā)初始標收集的閾值,定義為老年代大小的百分比

G1默認情況下通過觀察標記所花費的時間以及在標記周期內(nèi)老年代分配的內(nèi)存數(shù)量來自動確定最佳的IHOP,此功能稱為自適應(yīng)IHOP乾忱。如果此功能處于活動狀態(tài)讥珍,-XX:InitiatingHeapOccupancyPercent只有在沒有足夠的觀察值來進行預(yù)測時使用,選項-XX:-G1UseAdaptiveIHOP可以關(guān)閉G1的自適應(yīng)調(diào)整窄瘟,此時一直通過-XX:InitiatingHeapOccupancyPercent確定閾值

標記

G1標記使用Snapshot-At-The-Beginning (SATB) 算法衷佃。 在Initial Mark暫停時獲取堆的虛擬快照,在標記開始時存活的所有對象在后來的標記過程中都認為是存活對象蹄葱。這意味著在標記期間變?yōu)樗劳觯o法訪問)的對象在空間回收階段仍然被認為存活氏义,進行疏散 ,與其他收集器相比新蟆,這可能會導(dǎo)致錯誤地額外保留一些內(nèi)存觅赊。但是,SATB可以降低Remark階段的延遲

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琼稻,一起剝皮案震驚了整個濱河市吮螺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帕翻,老刑警劉巖鸠补,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嘀掸,居然都是意外死亡紫岩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門睬塌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泉蝌,“玉大人,你說我怎么就攤上這事揩晴⊙悖” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵硫兰,是天一觀的道長诅愚。 經(jīng)常有香客問我,道長劫映,這世上最難降的妖魔是什么违孝? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮泳赋,結(jié)果婚禮上雌桑,老公的妹妹穿的比我還像新娘。我一直安慰自己摹蘑,他們只是感情好筹燕,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般撒踪。 火紅的嫁衣襯著肌膚如雪过咬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天制妄,我揣著相機與錄音掸绞,去河邊找鬼。 笑死耕捞,一個胖子當著我的面吹牛衔掸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俺抽,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼敞映,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了磷斧?” 一聲冷哼從身側(cè)響起振愿,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弛饭,沒想到半個月后冕末,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡侣颂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年档桃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憔晒。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡藻肄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拒担,到底是詐尸還是另有隱情仅炊,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布澎蛛,位于F島的核電站,受9級特大地震影響蜕窿,放射性物質(zhì)發(fā)生泄漏谋逻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一桐经、第九天 我趴在偏房一處隱蔽的房頂上張望毁兆。 院中可真熱鬧,春花似錦阴挣、人聲如沸气堕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茎芭。三九已至揖膜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梅桩,已是汗流浹背壹粟。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宿百,地道東北人趁仙。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像垦页,于是被迫代替她去往敵國和親雀费。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容