一篇文章讓你了解GC垃圾回收器
簡單了解GC垃圾回收器
了解GC之前我們首先要了解GC是要做什麽的?顧名思義回收垃圾,什麽是垃圾呢?
GC回收的垃圾主要指的是回收堆內存中的垃圾對象。
從根對象出發,所有被引用的對象,都是存活對象 其他對象,都是垃圾對象。
根對象:
棧中的引用變量,所引用的對象。
方法區經靜態變量所引用的對象。
GC回收的三種基本方式
一、標記-清除
標記存活對象,清理其他垃圾對象(陰影為存活對象,空白為垃圾對象)
優點:效率高
缺點:產生碎片,使內存分布碎片化,造成內存空間不連續。若出現大的對象,內存空間不連續則難以存取
二、標記-整理
標記存活對象,清除垃圾對象,對垃圾對象進行整理
優點:沒有碎片
缺點:效率低
三、復制
在內存中分配兩塊內存,將標記的存活對象復制到另一塊內存當中,
再將原內存的對象清除。
優點:效率高
缺點:浪費內存
內存分區
新生代
老年代
永久代(方法區)(在Java8中,永久代已經被移除,被一個稱為“元數據區”(元空間)的區域所取代)
新生代
主要是用來存放新生的對象。一般占據堆的1/3空間。由於頻繁創建對象,所以新生代會頻繁觸發MinorGC進行垃圾回收
新生代又分為伊甸園與生存區,生存區分為ServivorFrom、ServivorTo
- Eden區(伊甸園):Java新對象的出生地(如果新創建的對象占用內存很大,則直接分配到老年代)。當Eden區內存不夠的時候就會觸發MinorGC,對新生代區進行一次垃圾回收。
- ServivorTo:保留了一次MinorGC過程中的幸存者。
- ServivorFrom:上一次GC的幸存者,作為這一次GC的被掃描者。
過程:
新建對象,在伊甸園分配內存
伊甸園存滿,復制到from
from存滿,復制到to,並交換角色
對象在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垃圾回收會優先選擇第一塊垃圾最多的區域
一篇文章讓你了解GC垃圾回收器