一篇文章讓你瞭解GC垃圾回收器
簡單瞭解GC垃圾回收器
瞭解GC之前我們首先要了解GC是要做什麼的?顧名思義回收垃圾,什麼是垃圾呢?
GC回收的垃圾主要指的是回收堆記憶體中的垃圾物件。
從根物件出發,所有被引用的物件,都是存活物件 其他物件,都是垃圾物件。
根物件:
棧中的引用變數,所引用的物件。
方法區經靜態變數所引用的物件。
GC回收的三種基本方式
一、標記-清除
標記存活物件,清理其他垃圾物件(陰影為存活物件,空白為垃圾物件)
優點:效率高
缺點:產生碎片,使記憶體分佈碎片化,造成記憶體空間不連續。若出現大的物件,記憶體空間不連續則難以存取
二、標記-整理
標記存活物件,清除垃圾物件,對垃圾物件進行整理
優點:沒有碎片
缺點:效率低
三、複製
在記憶體中分配兩塊記憶體,將標記的存活物件複製到另一塊記憶體當中,
再將原記憶體的物件清除。
優點:效率高
缺點:浪費記憶體
記憶體分割槽
新生代
老年代
永久代(方法區)(在Java8中,永久代已經被移除,被一個稱為“元資料區”(元空間)的區域所取代)
新生代
主要是用來存放新生的物件。一般佔據堆的1/3空間。由於頻繁建立物件,所以新生代會頻繁觸發MinorGC進行垃圾回收
新生代又分為伊甸園與生存區,生存區分為ServivorFrom、ServivorTo
- Eden區(伊甸園):Java新物件的出生地(如果新建立的物件佔用記憶體很大,則直接分配到老年代)。當Eden區記憶體不夠的時候就會觸發MinorGC,對新生代區進行一次垃圾回收。
- ServivorTo:保留了一次MinorGC過程中的倖存者。
- ServivorFrom:上一次GC的倖存者,作為這一次GC的被掃描者。
過程:
新建物件,在伊甸園分配記憶體
伊甸園存滿,複製到from
from存滿,複製到
物件在from,to之間複製15次,晉升到老年代
老年代
標記-清除、標記-整理
間隔一段時間,會執行一次小範圍垃圾回收
當老年代空間佔用到一定比例 0.85,會執行full-gc
當老年代也滿了裝不下的時候,就會丟擲OOM(Out of Memory)異常。
常見的垃圾回收器
- 序列垃圾回收器(Serial Garbage Collector)
- 並行垃圾回收器(Parallel Garbage Collector)
- 併發標記掃描垃圾回收器(CMS Garbage Collector)
- G1垃圾回收器(G1 Garbage Collector)
瞭解主要的兩種(CMS,G1)
CMS - 併發的標記-清除
STW(Stop The World)時間非常短暫
初始標記(stw)
只標記根物件
併發標記
垃圾回收器,與其他java程式並行執行
重新標記(stw)
併發清除
與其他java程式並行執行,配置引數過多,使用過於複雜
總結:
是一種以獲得最短回收停頓時間為目標的收集器,基於標記清除演算法。過程如下:初始標記,併發標記,重新標記,併發清除,
優點是併發收集,低停頓,缺點是對CPU資源非常敏感,無法處理浮動垃圾,收集結束會產生大量空間碎片。
G1 - Garbage First
記憶體被劃分成幾千個記憶體塊
有伊甸園、生存區、老年代
用複製演算法
G1會找到垃圾最多的記憶體塊,優先回收
配置引數非常簡單,只需要配置目標停頓時間(stw),G1自動調整其他引數,來達到預期的停頓時間
總結:G1垃圾回收器適用於堆記憶體很大的情況,他將堆記憶體分割成不同的區域,並且併發的對其進行垃圾回收。G1也可以在回收記憶體之後對剩餘的
堆記憶體空間進行壓縮。併發掃描標記垃圾回收器在STW情況下壓縮記憶體。G1垃圾回收會優先選擇第一塊垃圾最多的區域