《深入理解JAVA虛擬機器》JDK的垃圾收集演算法
概念
垃圾收集是很多使用JAVA語言的IT從業者瞭解得比較少的地方。
但是涉及效能時非常重要。大公司面試除了演算法,這部分也是會經常考察的地方。
《深入理解JAVA虛擬機器》一書中講到JVM的垃圾收集演算法和垃圾收集器。
垃圾收集演算法分為:
1、標記清除演算法
通常用在回收老年代記憶體。
最早的蒐集演算法就是標記清除(Mark-Sweep)演算法了。
其原理是分為標記和清除兩個階段:
首先標記出所有需要回收的物件,在標記完成後統一回收所有被標記的物件。
主要不足兩個:
一個是效率問題,標記過程和清除過程效率不高。
二是容易產生記憶體碎片,需要分配較大物件時,只能再觸發一次垃圾回收動作。
2、複製演算法
通常用在回收新生代記憶體。
複製演算法是目前也比較常用的演算法。
它的原理是:
將可用記憶體花費大小相等的三塊,兩塊是Survivor(倖存者分割槽),另外一塊是Eden(伊甸園分割槽)
每次只使用Eden和一個Survivor1分割槽,回收時,將當前Eden和Survivor中還活著的物件一次性的複製到另外一塊Survivor2空間上,如果記憶體不夠就向老年代記憶體區域借用記憶體空間進行分配。
也就說,如果Survivor2中記憶體不夠時,這些要回收的物件就會變成老年代記憶體,意味著這部分將使用老年代垃圾回收機制進行回收。
3、標記整理演算法
通常用在回收老年代記憶體。
它和標記清理演算法的差不多,主要區別是標記後,然後把物件進行排列整理,保留的放前面,要回收的放後面,然後回收後面那一堆垃圾物件。
優點是沒有碎片記憶體空間,記憶體利用率較高。
4、分代蒐集演算法
說白了其實就是把物件分為新生代、老年代,永久代(JDK8已經移除了永久代,引入元空間)。每一代使用上面列的一種垃圾回收演算法進行清理。
另外,由於老年代的記憶體物件,垃圾率比較高,基本都是要清理的,所以使用複製演算法不太好,佔用記憶體過多,這種情況下,一般使用標記-清除或者標記-整理演算法來清理。