【擁抱大廠系列】面試官100%會嚴刑拷打的 CMS 垃圾回收器,下次面試就拿這篇文章懟回去!

點個贊,看一看,好習慣!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收錄,這是我花了3個月總結的一線大廠Java面試總結,本人已拿騰訊等大廠offer。

這裏跟大家講個面試的最常見的垃圾回收器的問題,我跟大夥說,你不用懷疑,CMS垃圾回收器一定是最常見的問題,只要問到了Java虛擬機,面試官恨不得就問你CMS,當然還有就是G1這個垃圾回收器了,所以,關於這個垃圾回收器的細節問題,一定要掌握好,只要掌握到位,那麼一定可以讓面試官滿意。

但是,說句糟心的話,運氣不好,面試官就是不對眼,也是沒有辦法的事情,只能認栽,自我感覺再良好,也只是自我感覺,在面試官心裏,你就是渣渣!!!

好了,下面我們開始面試環節,這篇文章想換一種方式,我們列舉一些面試常見的問題,然後再來回答這些問題。

正文

這個春天,因爲疫情的原因,所有的面試都是線上遠程面試的,所以,如果運氣好,你可以看到面試官的臉,如果運氣不好,你可以只能被面試官看到你緊張的樣子,而你,看到的只是黑屏,哈哈!

這就是最真實的場景!

可是,並沒有面試官的身影,只有一次又一次的毒打!!

小夥子,你說一下 CMS 垃圾回收器吧!

這個題目一來,嚇出一身冷汗,差點就沒有複習這個CMS,還好昨晚抱佛腳看了一下哈。

於是我。。。一頓操作猛如虎。

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器,它是基於“標記-清除”算法實現的,並且常見的應用場景是互聯網站或者B/S系統的服務端上的Java應用

結果就一緊張就記得這麼多,面試官肯定不滿意了,這個時候,面試官的常規操作是,繼續嚴刑拷打,他想,你可能忘記了,我來提醒提醒你!

CMS收集器工作的整個流程是怎麼樣的,你能給我講講嗎?

這個時候,面試官還會安慰你說不用緊張,但是,安慰歸安慰,最後掛不掛可是另一回事。

於是,我又開始回答問題。

CMS 處理過程有七個步驟:

  • 初始標記,會導致stw;
  • 併發標記,與用戶線程同時運行;
  • 預清理,與用戶線程同時運行;
  • 可被終止的預清理,與用戶線程同時運行;
  • 重新標記 ,會導致swt;
  • 併發清除,與用戶線程同時運行;

其實,只要回答四個就差不多了,是這幾個。

  • 初始標記:僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,需要“Stop The World”。
  • 併發標記:進行GC Roots Tracing的過程,在整個過程中耗時最長。
  • 重新標記:爲了修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比並發標記的時間短。此階段也需要“Stop The World”。
  • 併發清除

你以爲這樣子就可以了,面試官就會說可以了,如果可以了,那估計你涼了!

面試官說:CMS這麼好,那有沒有什麼缺點呢?

我。。。好吧,誰怪我這麼強呢,對吧。

其實,CMS雖然經過這麼些年的考驗,已經是一個值得信賴的GC回收器了,但是,其實也是有一些他的不足的,

第一,垃圾碎片的問題,我們都知道CMS是使用的是標記-清除算法的,所以不可避免的就是會出現垃圾碎片的問題。
第二,一般CMS的GC耗時80%都在remark階段,remark階段停頓時間會很長,在CMS的這四個主要的階段中,最費時間的就是重新標記階段。
第三,concurrent mode failure,說出這個的時候,面試官就會覺得,小夥子,哎呦,不錯喲,掌握的比較清楚,那這個是什麼意思呢,其實是說:

這個異常發生在cms正在回收的時候。執行CMS GC的過程中,同時業務線程也在運行,當年輕帶空間滿了,執行ygc時,需要將存活的對象放入到老年代,而此時老年代空間不足,這時CMS還沒有機會回收老年帶產生的,或者在做Minor GC的時候,新生代救助空間放不下,需要放入老年代,而老年代也放不下而產生的。

第四,promotion failed,這個問題是指,在進行Minor GC時,Survivor空間不足,對象只能放入老年代,而此時老年代也放不下造成的,多數是由於老年代有足夠的空閒空間,但是由於碎片較多,新生代要轉移到老年帶的對象比較大,找不到一段連續區域存放這個對象導致的。

面試官看到你掌握的這麼好,心裏已經給你豎起來大拇指,但是,面試官覺得你優秀啊,就還想看看你到底還有多少東西。

既然你知道有這麼多的缺點,那麼你知道怎麼解決這些問題嗎?

這個真的被問蒙了,你以爲我什麼都會嗎!!!!

但是,我還是得給大家講講,不然下次被問到,可能會把鍋甩給我。

  • 垃圾碎片的問題:針對這個問題,這時候我們需要用到這個參數:-XX:CMSFullGCsBeforeCompaction=n 意思是說在上一次CMS併發GC執行過後,到底還要再執行多少次full GC纔會做壓縮。默認是0,也就是在默認配置下每次CMS GC頂不住了而要轉入full GC的時候都會做壓縮。

  • concurrent mode failure

解決這個問題其實很簡單,只需要設置兩個參數即可

-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=60:是指設定CMS在對內存佔用率達到60%的時候開始GC。

爲什麼設置這兩個參數呢?由於在垃圾收集階段用戶線程還需要運行,那也就還需要預留有足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集。

當然也不能設置過高,比如90%,這時候雖然GC次數少,但是,卻會導致用於用戶線程空間小,效率不高,太低10%,你自己想想會怎麼樣,體會體會!

哈哈,萬事大吉,這一點說出了,估計面試官已經愛上我了吧,趕緊把我招進去幹活吧。。。

  • remark階段停頓時間會很長的問題:解決這個問題巨簡單,加入-XX:+CMSScavengeBeforeRemark。在執行remark操作之前先做一次Young GC,目的在於減少年輕代對老年代的無效引用,降低remark時的開銷。

結尾

面到這裏,面試官給你說了一句:小夥子很優秀,思考問題很深入,什麼時候可以來我們公司實習,我們公司轉正機率很高啊,歡迎您的加入!

另外,我花了3個月時間把Java學習和麪試的總結整理成了一本電子書!目錄如下

現在免費分享大家,在我的公衆號好好學java回覆Java面試即可獲取。

有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章

1、老鐵們,關注我的原創微信公衆號「好好學java」,專注於Java、數據結構和算法、微服務、中間件等技術分享,保證你看完有所收穫。

2、給俺點個讚唄,可以讓更多的人看到這篇文章,順便激勵下我繼續寫作,嘻嘻。

點贊是對我最大的鼓勵
↓↓↓↓↓↓

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章