1. 程式人生 > >一篇文章讓你瞭解GC垃圾回收器

一篇文章讓你瞭解GC垃圾回收器

簡單瞭解GC垃圾回收器

瞭解GC之前我們首先要了解GC是要做什麼的?顧名思義回收垃圾,什麼是垃圾呢?

GC回收的垃圾主要指的是回收堆記憶體中的垃圾物件。

從根物件出發,所有被引用的物件,都是存活物件 其他物件,都是垃圾物件。

 根物件:

   棧中的引用變數,所引用的物件。

   方法區經靜態變數所引用的物件。

 GC回收的三種基本方式

一、標記-清除

  標記存活物件,清理其他垃圾物件(陰影為存活物件,空白為垃圾物件)

  優點:效率高

  缺點:產生碎片,使記憶體分佈碎片化,造成記憶體空間不連續。若出現大的物件,記憶體空間不連續則難以存取

 

二、標記-整理

  標記存活物件,清除垃圾物件,對垃圾物件進行整理 

  優點:沒有碎片

   缺點:效率低

三、複製

  在記憶體中分配兩塊記憶體,將標記的存活物件複製到另一塊記憶體當中,

  再將原記憶體的物件清除。

  優點:效率高

  缺點:浪費記憶體

 記憶體分割槽

   新生代

   老年代

   永久代(方法區)(在Java8中,永久代已經被移除,被一個稱為“元資料區”(元空間)的區域所取代)

 

新生代

  主要是用來存放新生的物件。一般佔據堆的1/3空間。由於頻繁建立物件,所以新生代會頻繁觸發MinorGC進行垃圾回收

 

 新生代又分為伊甸園與生存區,生存區分為ServivorFrom、ServivorTo

  • Eden區(伊甸園):Java新物件的出生地(如果新建立的物件佔用記憶體很大,則直接分配到老年代)。當Eden區記憶體不夠的時候就會觸發MinorGC,對新生代區進行一次垃圾回收。
  • ServivorTo:保留了一次MinorGC過程中的倖存者。
  • ServivorFrom:上一次GC的倖存者,作為這一次GC的被掃描者。

 

過程:

 新建物件,在伊甸園分配記憶體

 伊甸園存滿,複製到from

 from存滿,複製到

to,並交換角色

 物件在fromto之間複製15次,晉升到老年代

 

老年代

   標記-清除、標記-整理

   間隔一段時間,會執行一次小範圍垃圾回收

   當老年代空間佔用到一定比例 0.85,會執行full-gc

   當老年代也滿了裝不下的時候,就會丟擲OOM(Out of Memory)異常。

 

常見的垃圾回收器

 

  1. 序列垃圾回收器(Serial Garbage Collector)
  2. 並行垃圾回收器(Parallel Garbage Collector)
  3. 併發標記掃描垃圾回收器(CMS Garbage Collector)
  4. 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垃圾回收會優先選擇第一塊垃圾最多的區域