1. 程式人生 > >【BAT面試題系列】Java面試必考題JVM的最完整詳解,深度解析背後原理

【BAT面試題系列】Java面試必考題JVM的最完整詳解,深度解析背後原理

JVM是BAT面試中的Java必考題目。

 

想要完美解答JVM相關的面試問題,至少需要掌握JVM的記憶體管理、JVM垃圾回收演算法,及今天重點談到的JVM垃圾收集器(即JVM垃圾回收演算法的具體實現)。

 

Mike在本篇中為大家詳解,知其然,同時知其所以然,希望能夠幫助童鞋們順利通過JVM的面試考核。

 

01 JVM垃圾收集器發展歷程


第一階段,Serial(序列)收集器

在jdk1.3.1之前,java虛擬機器僅僅能使用Serial收集器。 Serial收集器是一個單執行緒的收集器,但它的“單執行緒”的意義並不僅僅是說明它只會使用一個CPU或一條收集執行緒去完成垃圾收集工作,更重要的是在它進行垃圾收集時,必須暫停其他所有的工作執行緒,直到它收集結束。

 

第二階段,Parallel(並行)收集器

Parallel收集器也稱吞吐量收集器,相比Serial收集器,Parallel最主要的優勢在於使用多執行緒去完成垃圾清理工作,這樣可以充分利用多核的特性,大幅降低gc時間。

 

第三階段,CMS(併發)收集器

CMS收集器在Minor GC時會暫停所有的應用執行緒,並以多執行緒的方式進行垃圾回收。在Full GC時不再暫停應用執行緒,而是使用若干個後臺執行緒定期的對老年代空間進行掃描,及時回收其中不再使用的物件。

 

第四階段,G1(併發)收集器

G1收集器(或者垃圾優先收集器)的設計初衷是為了儘量縮短處理超大堆(大於4GB)時產生的停頓。相對於CMS的優勢而言是記憶體碎片的產生率大大降低。

 

02 JVM垃圾收集器種類


1.新生代

Serial (第一代)

PraNew (第二代)

Parallel Scavenge (第三代)

G1收集器(第四代)

 

2.老年代

Serial Old (第一代)

Parallel Old (第二代)

CMS (第三代)

G1收集器 (第四代)

 

詳細的垃圾收集器比較,具體可以檢視我的往期分享《直通BAT必考題系列:7種JVM垃圾收集器特點,優劣勢、及使用場景》

JDK1.7後全新的JVM垃圾收集器G1收集器, 目標用於取代CMS收集器。

 

03 G1收集器概述


從JDK(1.3)開始,HotSpot團隊一直努力朝著高效收集、減少停頓(STW: Stop The World)的方向努力,也貢獻了從序列Serial收集器、到並行收集器Parallerl收集器,再到CMS併發收集器,乃至如今的G1在內的一系列優秀的垃圾收集器。

G1(Garbage First)垃圾收集器是當今垃圾回收技術最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成為HotSpot重點發展的垃圾回收技術。同優秀的CMS垃圾回收器一樣,G1也是關注最小時延的垃圾回收器,也同樣適合大尺寸堆記憶體的垃圾收集,官方也推薦使用G1來代替選擇CMS。

 

1.G1收集器的最大特點

G1最大的特點是引入分割槽的思路,弱化了分代的概念。

合理利用垃圾收集各個週期的資源,解決了其他收集器甚至CMS的眾多缺陷。

 

2.G1相比較CMS的改進

演算法: G1基於標記-整理演算法, 不會產生空間碎片,分配大物件時不會無法得到連續的空間而提前觸發一次FULL GC。

停頓時間可控: G1可以通過設定預期停頓時間(Pause Time)來控制垃圾收集時間避免應用雪崩現象。

並行與併發:G1能更充分的利用CPU,多核環境下的硬體優勢來縮短stop the world的停頓時間。

 

3.CMS和G1的區別

CMS中,堆被分為PermGen,YoungGen,OldGen;而YoungGen又分了兩個survivo區域。在G1中,堆被平均分成幾個區域(region),在每個區域中,雖然也保留了新老代的概念,但是收集器是以整個區域為單位收集的。

G1在回收記憶體後會馬上同時做合併空閒記憶體的工作、而CMS預設是在STW(stop the world)的時候做。

G1會在Young GC中使用、而CMS只能在O區使用。

 

4.G1收集器的應用場景

G1垃圾收集演算法主要應用在多CPU大記憶體的服務中,在滿足高吞吐量的同時,儘可能的滿足垃圾回收時的暫停時間。

就目前而言、CMS還是預設首選的GC策略、可能在以下場景下G1更適合,服務端多核CPU、JVM記憶體佔用較大的應用(至少大於4G),應用在執行過程中會產生大量記憶體碎片、需要經常壓縮空間,想要更可控、可預期的GC停頓週期,防止高併發下應用雪崩現象。

 

04 G1的堆記憶體演算法


1.G1之前的JVM記憶體模型

新生代:伊甸園區(eden space) + 2個倖存區

老年代

持久代(perm space):JDK1.8之前

元空間(metaspace):JDK1.8之後取代持久代

 

2.G1收集器的記憶體模型

1)G1堆記憶體結構

堆記憶體會被切分成為很多個固定大小區域(Region),每個是連續範圍的虛擬記憶體。

堆記憶體中一個區域(Region)的大小可以通過-XX:G1HeapRegionSize引數指定,大小區間最小1M、最大32M,總之是2的冪次方。

預設把堆記憶體按照2048份均分。

 

2)G1堆記憶體分配

每個Region被標記了E、S、O和H,這些區域在邏輯上被對映為Eden,Survivor和老年代。

存活的物件從一個區域轉移(即複製或移動)到另一個區域。區域被設計為並行收集垃圾,可能會暫停所有應用執行緒。

如上圖所示,區域可以分配到Eden,survivor和老年代。此外,還有第四種類型,被稱為巨型區域(Humongous Region)。Humongous區域是為了那些儲存超過50%標準region大小的物件而設計的,它用來專門存放巨型物件。如果一個H區裝不下一個巨型物件,那麼G1會尋找連續的H分割槽來儲存。為了能找到連續的H區,有時候不得不啟動Full GC。

 

05 G1回收流程


在執行垃圾收集時,G1以類似於CMS收集器的方式執行。

 

G1收集器的階段分以下幾個步驟:

1) G1執行的第一階段:初始標記(Initial Marking )

這個階段是STW(Stop the World )的,所有應用執行緒會被暫停,標記出從GC Root開始直接可達的物件。

2)  G1執行的第二階段:併發標記

從GC Roots開始對堆中物件進行可達性分析,找出存活物件,耗時較長。當併發標記完成後,開始最終標記(Final Marking )階段。

3)  最終標記(標記那些在併發標記階段發生變化的物件,將被回收)。
4)  篩選回收(首先對各個Regin的回收價值和成本進行排序,根據使用者所期待的GC停頓時間指定回收計劃,回收一部分Region)。

最後,G1中提供了兩種模式垃圾回收模式,Young GC和Mixed GC,兩種都是Stop The World(STW)的。

 

06 G1的GC模式


1.YoungGC年輕代收集

在分配一般物件(非巨型物件)時,當所有eden region使用達到最大閥值並且無法申請足夠記憶體時,會觸發一次YoungGC。每次younggc會回收所有Eden以及Survivor區,並且將存活物件複製到Old區以及另一部分的Survivor區。

 

YoungGC的回收過程如下:

1)根掃描,跟CMS類似,Stop the world,掃描GC Roots物件。

2)處理Dirty card,更新RSet。

3)掃描RSet,掃描RSet中所有old區對掃描到的young區或者survivor去的引用。

4)拷貝掃描出的存活的物件到survivor2/old區。

5)處理引用佇列,軟引用,弱引用,虛引用。

 

2.mixed gc

當越來越多的物件晉升到老年代old region時,為了避免堆記憶體被耗盡,虛擬機器會觸發一個混合的垃圾收集器,即mixed gc,該演算法並不是一個old gc,除了回收整個young region,還會回收一部分的old region,這裡需要注意:是一部分老年代,而不是全部老年代,可以選擇哪些old region進行收集,從而可以對垃圾回收的耗時時間進行控制。

G1沒有fullGC概念,需要fullGC時,呼叫serialOldGC進行全堆掃描(包括eden、survivor、o、perm)。

07 G1的推薦用例
G1的第一個重要特點是為使用者的應用程式的提供一個低GC延時和大記憶體GC的解決方案。這意味著堆大小6GB或更大,穩定和可預測的暫停時間將低於0.5秒。

如果應用程式使用CMS或ParallelOld垃圾回收器具有一個或多個以下特徵,將有利於切換到G1:

Full GC持續時間太長或太頻繁

物件分配率或年輕代升級老年代很頻繁

不期望的很長的垃圾收集時間或壓縮暫停(超過0.5至1秒)

注意:如果你正在使用CMS或ParallelOld收集器,並且你的應用程式沒有遇到長時間的垃圾收集暫停,則保持與您的當前收集器是很好的,升級JDK並不必要更新收集器為G1。

-end-

 

往期熱文:

高併發架構系列:Redis快取和MySQL資料一致性方案詳解

碼了幾年程式碼的程式設計師,有一定的開發經驗,應該如何提升自己?

最全BAT等大廠Java 面試題目1000+,能答對70%就去BATJTMD試試~

 

覺得不錯請點贊支援,歡迎留言或進我的個人群179961551領取【100期架構資料專題合集】、【1000+道大廠JAVA面試真題】,本群專用於學習交流技術、分享面試機會,拒絕廣告,我也會在群內不定期答題、探討。