1. 程式人生 > >JVM學習記錄-垃圾回收算法

JVM學習記錄-垃圾回收算法

image 不同 基於 copy 效率問題 bsp 堆內存 而是 相等

簡述

因為各個平臺的虛擬機的垃圾收集器的實現各有不同,所以只介紹幾個常見的垃圾收集算法。

JVM中常見的垃圾收集算法有以下四種:

標記-清除算法(Mark-Sweep)。

復制算法(Copying)。

標記整理算法(Mark-Compact)。

分代收集算法(Generational Collecting)。

標記-清除算法

標記-清除算法是現代垃圾回收算法的思想基礎,主要分為兩個階段:標記階段和清除階段。首先根據可達分析算法,標記處可以回收的對象,標記完成後,進行清除階段,將標記為可回收的對象進行清除。這個算法有兩個弱點,一個弱點是效率問題,標記和清除效率都不高,另一弱點,也是最大的弱點就是會產生空間碎片。當內存中空間碎片過多時,在創建較大的對象過程中,無法分配出足夠的聯系內存空間,會不得以的出發一次垃圾回收動作。

標記-清除算法執行過程如下圖所示:

技術分享圖片

復制算法

與標記-清除算法相比,復制算法是一種相對效率高的回收算法,它的核心思想是:將原有的內存空間劃分為大小相等的兩塊,每次只使用其中一塊,在垃圾回收時,將正在使用的內存中的存活的對象復制到未使用的的內存塊中,然後清除正在使用的內存塊,然後交換兩個內存的角色(即使用塊變成未使用塊,未使用塊變成使用塊)。復制算法可以保證回收後沒有空間碎片。但是復制算法的弱點是將系統可用內存折半,這個代價有些太大。

執行過程如下:

技術分享圖片

在JVM的新生代(堆內存分為新生代老年代)中就是使用的這種收集算法,在新生代中大部分對象都是“朝生夕死”,所以復制算法也不是非要按照對半平分內存,而是分為較大的一個Eden

空間和兩個較小的Survivor空間(from和to),每次進行新生代回收時會將Eden區from Survivor區還存活著的對象復制到to Survivor區,然後清理掉Eden區和from Survivor區的可回收對象,如果to Survivor區中沒有足夠的空間來接受還存活著的對象,則會把多余的對象放到老年代區。這種改進的(非平分內存)復制算法,既保證了空間的連續性,又避免了大量的內存空間的浪費。

復制算法適用於新生代,是因為在新生代中,垃圾對象通常多於存活對象,這中情況適用復制算法效果會比較好。

標記整理算法

復制算法的高效性,是因為新生代的存活對象多,垃圾對象少。但是在老年代中,常見的情況下大部分都是存活對象,如果依然只用復制算法,效率就會大大折扣。因為存活對象太多,復制的成本太高了。

基於老年代的特點,產生了一種標記整理算法,標記整理算法也是分兩個階段,標記階段整理階段,標記階段也是先標記出存活的對象,在整理階段是將存活的對象都向內存的一端進行壓縮移動,然後清理掉端邊界以外的空間。

標記整理算法執行過程如下:

技術分享圖片

這種算法既避免了產生空間碎片,又不需要將內存平分,因此效率還是可以的。

分代收集算法

當前的商業虛擬機都采用“分代收集算法”,其主要思想是:根據垃圾回收對象的特性,使用合適的算法進行回收。基於這種思想,分代算法將堆內存分為特點鮮明的幾塊,根據每塊的特點,選擇適用的收集算法,進而提高回收效率。

在新生代時使用復制算法,在老年代時使用標記壓縮算法。

這種分代算法在HotSpot虛擬機上使用,幾乎所有的垃圾回收器都區分新生代和老年代。

JVM學習記錄-垃圾回收算法