1. 程式人生 > >JVM的幾種垃圾收集演算法

JVM的幾種垃圾收集演算法

       在我以前學習C++語言時,很頭疼的一個問題就是記憶體的分配,C++需要我們自己分配記憶體,用完的時候還需要自己釋放,當我們開發人員一旦出現疏忽忘記釋放資源的時候,累積起來就很容易丟擲OutOfMemoryError異常。


       後來我轉到了Java開發,隨著慢慢的深入後,我接觸到了Java虛擬機器(下面就叫jvm了),在記憶體這個問題上,jvm可以自動為我們回收一些未被引用的物件,從而達到釋放資源的目的,這樣就不再需要我們開發人員自己去分配、釋放資源了。


       jvm

為我們分配、釋放資源的同時,也為我們關上了一扇窗戶,就是這一切都交給了jvm來做,當丟擲OutOfMemoryError異常時,我們很難馬上知道問題出在哪個環節上。所以Java開發者很有必要來學習下jvm的原理知識。


下面我將介紹jvm的幾種垃圾收集演算法。

1.標記-清除演算法

     “標記-清除演算法”算是最基礎的收集演算法了,正如名字而言,標記-清除演算法”分為兩個階段:“標記”和“清除”。首先標記出所有需要被回收的物件,在標記完成後統一回收所有被標記的物件。

       這種演算法很好理解,但是它有兩個不足:一是效率低;二是標記清除之後會產生大量不連續的記憶體碎片,但某個物件需要分配一塊大記憶體的時候,這些不連續的小的記憶體碎片用不上。


2.複製演算法

       複製演算法將可用記憶體按容量劃分為大小相等的兩塊,每次只使用其中的一塊,當這一塊的記憶體用完了,就將還存活著的物件複製到另外一塊上面,然後再把已使用過的記憶體空間一次清理掉。這樣每次都是對整個半區進行記憶體回收,記憶體分配時也就不用考慮記憶體碎片的複雜情況。

       這種演算法的優點是:實現簡單,執行高效。但也有很明顯的不足:就是將記憶體縮小為了原來的一半,成本有點高。

       現在一般採用這種演算法來回收新生代的資源。



3.標記-整理演算法

       根據老年代資源的特點,有人提出了“標記-整理演算法”,標記過程仍然與“標記-清除演算法”一樣,但後續步驟不是直接對可回收物件進行清理,而是讓所有存貨的物件都向一端移動,然後直接清理掉端邊界以外的記憶體。


4.分代收集演算法

根據物件存活週期的不同將記憶體劃分為新生代和老年代。這樣就可以根據各個年代的特點採用最適當的收集演算法。在新生代中,每次垃圾收集時都發現有大批物件死去,只有少量存活,這樣就選用複製演算法,只需要付出少量存活物件的複製成本就可以完成收集。而老年代中因為物件存活率高,沒有額外空間對它進行分配擔保,就必須使用“標記-清理”或者“標記-整理”演算法來進行回收。