主頁 > 後端開發 > 難頂!面試官問我G1垃圾收集器

難頂!面試官問我G1垃圾收集器

2021-11-11 09:50:36 後端開發

面試官要不這次來聊聊G1垃圾收集器?

候選者:嗯嗯,好的呀

候選者:上次我記得說過,CMS垃圾收集器的弊端:會產生記憶體碎片&&空間需要預留

候選者:這倆個問題在處理的時候,很有可能會導致停頓時間過長,說白了就是CMS的停頓時間是「不可預知的」

候選者:而G1又可以理解為在CMS垃圾收集器上進行"升級"

候選者:G1 垃圾收集器可以給你設定一個你希望Stop The Word 停頓時間,G1垃圾收集器會根據這個時間盡量滿足你

候選者:在前面我在介紹JVM堆的時候,是畫了一張圖的,堆的記憶體分布是以「物理」空間進行隔離

候選者:在G1垃圾收集器的世界上,堆的劃分不再是「物理」形式,而是以「邏輯」的形式進行劃分

候選者:不過,像之前說過的「分代」概念在G1垃圾收集器的世界還是一樣奏效的

候選者:比如說:新物件一般會分配到Eden區、經過默認15次的Minor GC新生代的物件如果還存活,會移交到老年代等等...

候選者:我來畫下G1垃圾收集器世界的「堆」空間分布吧

候選者:從圖上就可以發現,堆被劃分了多個同等份的區域,在G1里每個區域叫做Region

候選者:老年代、新生代、Survivor這些應該就不用我多說了吧?規則是跟CMS一樣的

候選者:G1中,還有一種叫 Humongous(大物件)區域,其實就是用來存盤特別大的物件(大于Region記憶體的一半)

候選者:一旦發現沒有參考指向大物件,就可直接在年輕代的Minor GC中被回收掉

面試官:嗯...

候選者:其實稍微想一下,也能理解為什么要將「堆空間」進行「細分」多個小的區域

候選者:像以前的垃圾收集器都是對堆進行「物理」劃分

候選者:如果堆空間(記憶體)大的時候,每次進行「垃圾回收」都需要對一整塊大的區域進行回收,那收集的時間是不好控制的

候選者:而劃分多個小區域之后,那對這些「小區域」回收就容易控制它的「收集時間」了

面試官:嗯...

面試官那我大概了解了,那要不你講講它的GC程序唄?

候選者:嗯,在G1收集器中,可以主要分為有Minor GC(Young GC)和Mixed GC,也有些特殊場景可能會發生Full GC

候選者:那我就直接說Minor GC先咯?

面試官:嗯,開始吧

候選者:G1的Minor GC其實觸發時機跟前面提到過的垃圾收集器都是一樣的

候選者:等到Eden區滿了之后,會觸發Minor GC,Minor GC同樣也是會發生Stop The World的

候選者:要補充說明的是:在G1的世界里,新生代和老年代所占堆的空間是沒那么固定的(會動態根據「最大停頓時間」進行調整)

候選者:這塊要知道會給我們提供引數進行配置就好了

候選者:所以,動態地改變年輕代Region的個數可以「控制」Minor GC的開銷

面試官嗯,那Minor GC它的回收程序呢?可以稍微詳細補充一下嗎

候選者:Minor GC我認為可以簡單分為為三個步驟:根掃描、更新&&處理 RSet、復制物件

候選者:第一步應該很好理解,因為這跟之前CMS是類似的,可以理解為初始標記的程序

候選者:第二步涉及到「Rset」的概念

面試官:嗯...

候選者:從上一次我們聊CMS回收程序的時候,同樣講到了Minor GC,它是通過「卡表」(cart table)來避免全表掃描老年代的物件

候選者:因為Minor GC 是回收年輕代的物件,但如果老年代有物件參考著年輕代,那這些被老年代參考的物件也不能回收掉

候選者:同樣的,在G1也有這種問題(畢竟是Minor GC),CMS是卡表,而G1解決「跨代參考」的問題的存盤一般叫做RSet

候選者:只要記住,RSet這種存盤在每個Region都會有,它記錄著「其他Region參考了當前Region的物件關系」

候選者:對于年輕代的Region,它的RSet 只保存了來自老年代的參考(因為年輕代的沒必要存盤啊,自己都要做Minor GC了)

候選者:而對于老年代的 Region 來說,它的 RSet 也只會保存老年代對它的參考(在G1垃圾收集器,老年代回收之前,都會先對年輕代進行回收,所以沒必要保存年輕代的參考)

面試官:嗯...

候選者:那第二步看完RSet的概念,應該也好理解了吧?

候選者:無非就是處理RSet的資訊并且掃描,將老年代物件持有年輕代物件的相關參考都加入到GC Roots下,避免被回收掉

候選者:到了第三步也挺好理解的:把掃描之后存活的物件往「空的Survivor區」或者「老年代」存放,其他的Eden區進行清除

候選者:這里要提下的是,在G1還有另一個名詞,叫做CSet,

候選者:它的全稱是 Collection Set,保存了一次GC中「將執行垃圾回收」的Region,CSet中的所有存活物件都會被轉移到別的可用Region上

候選者:在Minor GC 的最后,會處理下軟參考、弱參考、JNI Weak等參考,結束收集

面試官:嗯,了解了,不難

面試官我記得你前面提到了Mixed GC ,要不來聊下這個程序唄?

候選者:好,沒問題的,

候選者:當堆空間的占用率達到一定閾值后會觸發Mixed GC(默認45%,由引數決定)

候選者:Mixed GC 依賴「全域并發標記」統計后的Region資料

候選者:「全域并發標記」它的程序跟CMS非常型別,步驟大概是:初始標記(STW)、并發標記、最終標記(STW)以及清理(STW)

面試官:確實很像啊,你繼續來聊聊具體的程序唄?

候選者:嗯嗯,還是想說明下:Mixed GC它一定會回收年輕代,并會采集部分老年代的Region進行回收的,所以它是一個“混合”GC,

候選者:首先是「初始標記」,這個程序是「共用」了Minor GC的 Stop The World(Mixed GC 一定會發生 Minor GC),復用了「掃描GC Roots」的操作,

候選者:在這個程序中,老年代和新生代都會掃

候選者:總的來說,「初始標記」這個程序還是比較快的,畢竟沒有追溯遍歷嘛

面試官:...

候選者:接下來就到了「并發標記」,這個階段不會Stop The World

候選者:GC執行緒與用戶執行緒一起執行,GC執行緒負責收集各個 Region 的存活物件資訊

候選者:從GC Roots往下追溯,查找整個堆存活的物件,比較耗時

面試官:嗯...

候選者:接下來就到「重新標記」階段,跟CMS又一樣,標記那些在「并發標記」階段發生變化的物件

候選者:是不是很簡單?

面試官:且慢

面試官CMS在「重新標記」階段,應該會重新掃描所有的執行緒堆疊和整個年輕代作為root

面試官據我了解,G1好像不是這樣的,這塊你了解嗎?

候選者:嗯,G1 確實不是這樣的,在G1中解決「并發標記」階段導致參考變更的問題,使用的是SATB演算法

候選者:可以簡單理解為:在GC 開始的時候,它為存活的物件做了一次「快照」

候選者:在「并發階段」時,把每一次發生參考關系變化時舊的參考值給記下來

候選者:然后在「重新標記」階段只掃描著塊「發生過變化」的參考,看有沒有物件還是存活的,加入到「GC Roots」上

候選者:不過SATB演算法有個小的問題,就是:如果在開始時,G1就認為它是活的,那就在此次GC中不會對它回收,即便可能在「并發階段」上物件已經變為了垃圾,

候選者:所以,G1也有可能會存在「浮動垃圾」的問題

候選者:但是總的來說,對于G1而言,問題不大(畢竟它不是追求一次把所有的垃圾都清除掉,而是注重 Stop The World時間)

面試官:嗯...

候選者:最后一個階段就是「清理」,這個階段也是會Stop The World的,主要清點和重置標記狀態

候選者:會根據「停頓預測模型」(其實就是設定的停頓時間),來決定本次GC回收多少Region

候選者:一般來說,Mixed GC會選定所有的年輕代Region,部分「回收價值高」的老年代Region(回收價值高其實就是垃圾多)進行采集

候選者:最后Mixed GC 進行清除還是通過「拷貝」的方式去干的

候選者:所以,一次回收未必是將所有的垃圾進行回收的,G1會依據停頓時間做出選擇Region數量(:

面試官:嗯,程序我大致是了解了

面試官那G1會什么時候發生full GC?

候選者:如果在Mixed GC中無法跟上用戶執行緒分配記憶體的速度,導致老年代填滿無法繼續進行Mixed GC,就又會降級到serial old GC來收集整個GC heap

候選者:不過這個場景相較于CMS還是很少的,畢竟G1沒有CMS記憶體碎片這種問題(:

本文總結(G1垃圾收集器特點):

  • 從原來的「物理」分代,變成現在的「邏輯」分代,將堆記憶體「邏輯」劃分為多個Region
  • 使用CSet來存盤可回收Region的集合
  • 使用RSet來處理跨代參考的問題(注意:RSet不保留 年輕代相關的參考關系)
  • G1可簡單分為:Minor GC 和Mixed GC以及Full GC
  • 【Eden區滿則觸發】Minor GC 回收程序可簡單分為:(STW) 掃描 GC Roots、更新&&處理Rset、復制清除
  • 【整堆空間占一定比例則觸發】Mixed GC 依賴「全域并發標記」,得到CSet(可回收Region),就進行「復制清除」
  • R大描述G1原理的時候,從宏觀的角度看G1其實就是「全域并發標記」和「拷貝存活物件
  • 使用SATB演算法來處理「并發標記」階段物件參考可能會修改的問題
  • 提供可停頓時間引數供用戶設定(G1會盡量滿足該停頓時間來調整 GC時回收Region的數量

歡迎關注我的微信公眾號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!

【對線面試官-移動端】系列 一周兩篇持續更新中!

【對線面試官-電腦端】系列 一周兩篇持續更新中!

原創不易!!求三連!!

更多的文章可往:文章的目錄導航

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/355440.html

標籤:其他

上一篇:支撐千萬級并發的架構師如何一步步演進的?

下一篇:支撐千萬級并發的架構師如何一步步演進的?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more