直通BAT必考题系列:深入剖析JVM之G1收集器、及回收流程、与推荐用例
金三銀四馬上到了,即將進入面試的高峰期。在BAT面試中,JVM基本都是必考的系列。你至少需要掌握JVM內(nèi)存模型與JVM參數(shù)詳細配置,JVM的4種垃圾回收算法、垃圾回收機制與總結(jié),以及今天重點談到的JVM垃圾回收算法的實現(xiàn):JVM垃圾收集器。
我先從JVM收集器的發(fā)展過程談起,然后再聚焦在G1收集器,從G1的內(nèi)存模型,再到G1的回收流程,最后再談?wù)凣1的實際應(yīng)用場景。
JVM垃圾收集器發(fā)展歷程
JVM垃圾收集器發(fā)展歷程
第一階段,Serial(串行)收集器
在jdk1.3.1之前,java虛擬機僅僅能使用Serial收集器。 Serial收集器是一個單線程的收集器,但它的“單線程”的意義并不僅僅是說明它只會使用一個CPU或一條收集線程去完成垃圾收集工作,更重要的是在它進行垃圾收集時,必須暫停其他所有的工作線程,直到它收集結(jié)束。
第二階段,Parallel(并行)收集器
Parallel收集器也稱吞吐量收集器,相比Serial收集器,Parallel最主要的優(yōu)勢在于使用多線程去完成垃圾清理工作,這樣可以充分利用多核的特性,大幅降低gc時間。
第三階段,CMS(并發(fā))收集器
CMS收集器在Minor GC時會暫停所有的應(yīng)用線程,并以多線程的方式進行垃圾回收。在Full GC時不再暫停應(yīng)用線程,而是使用若干個后臺線程定期的對老年代空間進行掃描,及時回收其中不再使用的對象。
第四階段,G1(并發(fā))收集器
G1收集器(或者垃圾優(yōu)先收集器)的設(shè)計初衷是為了盡量縮短處理超大堆(大于4GB)時產(chǎn)生的停頓。相對于CMS的優(yōu)勢而言是內(nèi)存碎片的產(chǎn)生率大大降低。
JVM垃圾收集器種類
JVM垃圾收集器
1.新生代
- Serial (第一代)
- PraNew (第二代)
- Parallel Scavenge (第三代)
- G1收集器(第四代)
2.老年代
- Serial Old (第一代)
- Parallel Old (第二代)
- CMS (第三代)
- G1收集器 (第四代)
詳細的垃圾收集器比較,具體可以查看:直通BAT必考題系列:7種JVM垃圾收集器特點,優(yōu)劣勢、及使用場景
JDK1.7后全新的JVM垃圾收集器G1收集器, 目標用于取代CMS收集器。
G1收集器概述
從JDK(1.3)開始,HotSpot團隊一直努力朝著高效收集、減少停頓(STW: Stop The World)的方向努力,也貢獻了從串行Serial收集器、到并行收集器Parallerl收集器,再到CMS并發(fā)收集器,乃至如今的G1在內(nèi)的一系列優(yōu)秀的垃圾收集器。
G1(Garbage First)垃圾收集器是當今垃圾回收技術(shù)最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成為HotSpot重點發(fā)展的垃圾回收技術(shù)。同優(yōu)秀的CMS垃圾回收器一樣,G1也是關(guān)注最小時延的垃圾回收器,也同樣適合大尺寸堆內(nèi)存的垃圾收集,官方也推薦使用G1來代替選擇CMS。
1.G1收集器的最大特點
- G1最大的特點是引入分區(qū)的思路,弱化了分代的概念。
- 合理利用垃圾收集各個周期的資源,解決了其他收集器甚至CMS的眾多缺陷。
2.G1相比較CMS的改進
- 算法: G1基于標記-整理算法, 不會產(chǎn)生空間碎片,分配大對象時不會無法得到連續(xù)的空間而提前觸發(fā)一次FULL GC。
- 停頓時間可控: G1可以通過設(shè)置預期停頓時間(Pause Time)來控制垃圾收集時間避免應(yīng)用雪崩現(xiàn)象。
- 并行與并發(fā):G1能更充分的利用CPU,多核環(huán)境下的硬件優(yōu)勢來縮短stop the world的停頓時間。
3.CMS和G1的區(qū)別
- CMS中,堆被分為PermGen,YoungGen,OldGen;而YoungGen又分了兩個survivo區(qū)域。在G1中,堆被平均分成幾個區(qū)域(region),在每個區(qū)域中,雖然也保留了新老代的概念,但是收集器是以整個區(qū)域為單位收集的。
- G1在回收內(nèi)存后會馬上同時做合并空閑內(nèi)存的工作、而CMS默認是在STW(stop the world)的時候做。
- G1會在Young GC中使用、而CMS只能在O區(qū)使用。
4.G1收集器的應(yīng)用場景
G1垃圾收集算法主要應(yīng)用在多CPU大內(nèi)存的服務(wù)中,在滿足高吞吐量的同時,盡可能的滿足垃圾回收時的暫停時間。
就目前而言、CMS還是默認首選的GC策略、可能在以下場景下G1更適合:
- 服務(wù)端多核CPU、JVM內(nèi)存占用較大的應(yīng)用(至少大于4G)
- 應(yīng)用在運行過程中會產(chǎn)生大量內(nèi)存碎片、需要經(jīng)常壓縮空間
- 想要更可控、可預期的GC停頓周期,防止高并發(fā)下應(yīng)用雪崩現(xiàn)象
G1的堆內(nèi)存算法
1.G1之前的JVM內(nèi)存模型
- 新生代:伊甸園區(qū)(eden space) + 2個幸存區(qū)
- 老年代
- 持久代(perm space):JDK1.8之前
- 元空間(metaspace):JDK1.8之后取代持久代
2.G1收集器的內(nèi)存模型
1)G1堆內(nèi)存結(jié)構(gòu)
堆內(nèi)存會被切分成為很多個固定大小區(qū)域(Region),每個是連續(xù)范圍的虛擬內(nèi)存。
堆內(nèi)存中一個區(qū)域(Region)的大小可以通過-XX:G1HeapRegionSize參數(shù)指定,大小區(qū)間最小1M、最大32M,總之是2的冪次方。
默認把堆內(nèi)存按照2048份均分。
2)G1堆內(nèi)存分配
每個Region被標記了E、S、O和H,這些區(qū)域在邏輯上被映射為Eden,Survivor和老年代。
存活的對象從一個區(qū)域轉(zhuǎn)移(即復制或移動)到另一個區(qū)域。區(qū)域被設(shè)計為并行收集垃圾,可能會暫停所有應(yīng)用線程。
如上圖所示,區(qū)域可以分配到Eden,survivor和老年代。此外,還有第四種類型,被稱為巨型區(qū)域(Humongous Region)。Humongous區(qū)域是為了那些存儲超過50%標準region大小的對象而設(shè)計的,它用來專門存放巨型對象。如果一個H區(qū)裝不下一個巨型對象,那么G1會尋找連續(xù)的H分區(qū)來存儲。為了能找到連續(xù)的H區(qū),有時候不得不啟動Full GC。
G1回收流程
在執(zhí)行垃圾收集時,G1以類似于CMS收集器的方式運行。
1.G1收集器的階段分以下幾個步驟:
1)G1執(zhí)行的第一階段:初始標記(Initial Marking )
這個階段是STW(Stop the World )的,所有應(yīng)用線程會被暫停,標記出從GC Root開始直接可達的對象。
2)G1執(zhí)行的第二階段:并發(fā)標記
從GC Roots開始對堆中對象進行可達性分析,找出存活對象,耗時較長。當并發(fā)標記完成后,開始最終標記(Final Marking )階段
3)最終標記(標記那些在并發(fā)標記階段發(fā)生變化的對象,將被回收)
4)篩選回收(首先對各個Regin的回收價值和成本進行排序,根據(jù)用戶所期待的GC停頓時間指定回收計劃,回收一部分Region)
最后,G1中提供了兩種模式垃圾回收模式,Young GC和Mixed GC,兩種都是Stop The World(STW)的。
G1的GC模式
1.YoungGC年輕代收集
在分配一般對象(非巨型對象)時,當所有eden region使用達到最大閥值并且無法申請足夠內(nèi)存時,會觸發(fā)一次YoungGC。每次younggc會回收所有Eden以及Survivor區(qū),并且將存活對象復制到Old區(qū)以及另一部分的Survivor區(qū)。
YoungGC的回收過程如下:
- 根掃描,跟CMS類似,Stop the world,掃描GC Roots對象。
- 處理Dirty card,更新RSet.
- 掃描RSet,掃描RSet中所有old區(qū)對掃描到的young區(qū)或者survivor去的引用。
- 拷貝掃描出的存活的對象到survivor2/old區(qū)
- 處理引用隊列,軟引用,弱引用,虛引用
2.mixed gc
當越來越多的對象晉升到老年代old region時,為了避免堆內(nèi)存被耗盡,虛擬機會觸發(fā)一個混合的垃圾收集器,即mixed gc,該算法并不是一個old gc,除了回收整個young region,還會回收一部分的old region,這里需要注意:是一部分老年代,而不是全部老年代,可以選擇哪些old region進行收集,從而可以對垃圾回收的耗時時間進行控制。
G1沒有fullGC概念,需要fullGC時,調(diào)用serialOldGC進行全堆掃描(包括eden、survivor、o、perm)。
G1的推薦用例
G1的第一個重要特點是為用戶的應(yīng)用程序的提供一個低GC延時和大內(nèi)存GC的解決方案。這意味著堆大小6GB或更大,穩(wěn)定和可預測的暫停時間將低于0.5秒。
如果應(yīng)用程序使用CMS或ParallelOld垃圾回收器具有一個或多個以下特征,將有利于切換到G1:
- Full GC持續(xù)時間太長或太頻繁
- 對象分配率或年輕代升級老年代很頻繁
- 不期望的很長的垃圾收集時間或壓縮暫停(超過0.5至1秒)
注意:如果你正在使用CMS或ParallelOld收集器,并且你的應(yīng)用程序沒有遇到長時間的垃圾收集暫停,則保持與您的當前收集器是很好的,升級JDK并不必要更新收集器為G1。
你可能也喜歡:
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的直通BAT必考题系列:深入剖析JVM之G1收集器、及回收流程、与推荐用例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 根因分析初探:一种报警聚类算法在业务系统
- 下一篇: RDS平台介绍