天天看點

JVM學習筆記——GC算法

  GC 即 Garbage Collection 垃圾回收。JVM 中的 GC 99%發生在堆中,而 Java 堆中采用的垃圾回收機制為分代收集算法。即将堆分為新生代和老年代,根據不同的區域使用不同的垃圾回收算法。

  給每個對象設定一個引用計數器,每有一個地方引用此對象時,計數器 +1,引用失效計數器 -1。當對象計數器為0時,将會被垃圾回收。

  引用計數器無法解決循環引用的問題。當AB兩個對象都無其他對象引用,且 A 對象引用 B 對象,B 對象也引用 A 對象時,兩個對象本應被回收,但計數器都不為0,無法垃圾回收。

  是以主流虛拟機都未采用此算法。

  從一個被視為 GC Roots 的對象開始向下搜尋,如果一個對象到 GC Roots 沒有任何引用鍊相連時,說明此對象不可用,可以被垃圾回收。

 Java 中可作為 GC Roots 的對象如下:

虛拟機棧中引用的對象

方法區類靜态屬性引用的對象

方法區常量池引用的對象

本地方法棧 JNI 引用的對象

  當一個對象不可達 GC Roots 時,這個對象不會立馬被回收,而是處于死緩的階段,若要真正被回收需要經曆兩次标記。

  被第一次标記的對象會經曆一次篩選,篩選是否有必要進行<code>finalize()</code>方法,對象如果已被虛拟機調用過或認定沒必要執行<code>finalize()</code>方法,則立即回收。

  如果需要執行<code>finalize()</code>方法,則把對象放入 F-Queue 隊列中,等待<code>Finalize()</code>線程執行,該線程為低優先級,且不被 JVM 承諾執行完畢。GC對 F-Queue 隊列中的對象進行二次标記,被标記後等待回收。

  最基礎的垃圾回收算法,分兩個階段,标記,清除。标記所需回收的對象,清除被标記的對象。

  看似簡單,但該算法最大的問題在于記憶體碎片化嚴重,如果清理後不整理記憶體,整塊記憶體就會被存活的對象分割成一塊塊較小的連續空間,當需要建立較大對象時會難以在記憶體中找到合适的連續空間。

節約空間

需要進行兩次掃描,耗時嚴重

記憶體碎片化嚴重

老年代标記清除,标記壓縮結合使用

  為了解決标記清除算法記憶體碎片化的缺陷而被提出。

  按記憶體容量将記憶體劃分為兩塊,每次隻使用其中一塊,當一塊記憶體存滿後,将存活的對象複制至另一塊,清空目前塊内的記憶體,然後兩邊互換使用。

算法實作簡單,記憶體效率高,不易産生碎片

使用空間被壓縮,浪費了一點空間,如果存活對象增多,算法效率會大大降低

  結合标記清除算法和複制算法被提出。

算法思想:

标記死亡對象

将存活對象移動至記憶體另一端

清除端邊界外所有對象

JVM學習筆記——GC算法

  

JVM學習筆記——GC算法

 特點:

記憶體連續,不産生碎片

效率不高,要标記存活對象,整理對象引用位址,效率低于複制算法

上一篇: Ruby 判斷