問題:請講下在java中有哪些垃圾回收演算法
分析:該問題主要考察對java中垃圾回收的演算法以及使用場景
回答要點:
主要從以下幾點去考慮,
1、GC回收演算法有哪些
2、每種演算法的使用場景
3、基於垃圾回收演算法有哪些垃圾回收器
在《java面試一日一題:如何判斷一個物件是否為垃圾物件》中知道了java中判斷一個物件是否存活,是否可被回收使用的是可達性分析演算法,找出了可回收的物件,那麼有哪些回收演算法可以回收這些物件那
複製演算法
複製演算法就是從一個地方複製到另外一個地方,針對垃圾回收來說,就是把活著的物件複製到另外一塊記憶體區域,然後之前的記憶體區域中的物件便可以被回收。在同等大小記憶體前提下,複製演算法的記憶體使用率比較低,因為它會把記憶體分為兩個部分,如下圖
複製演算法-回收前
複製演算法-回收後
標記-清除演算法
標記-清除演算法,首先是一個標記的過程,也就是標記出哪些物件是垃圾,然後進行清除操作。該演算法不需要像複製演算法似的,把記憶體分為兩部分,它可以利用整塊的記憶體,在記憶體利用率上是沒有問題的,但是容易產生記憶體碎片,隨著記憶體的回收,可能在記憶體中就不存在整塊的大記憶體,在分配需要連續空間的大物件(陣列)時就會發生OOM。如下圖
標記清除-演算法前
標記清除-演算法後
從上圖可以看到在使用標記-清除演算法後,被標記為垃圾的物件被回收了,釋放了記憶體空間,但是記憶體中存在了一個隔一個的空,也就是記憶體碎片,這時如果要分配一個連續的大空間,可能有無法找到空間的情況,發生OOM。
另外,使用標記-清除演算法,在進行記憶體分配的時候採用的記憶體分配演算法一定是空閒列表法。
標記-整理/壓縮演算法
標記-整理/壓縮,是在標記清除的基礎上加了一個記憶體整理的過程,是為了消除記憶體碎片的,如下圖
標記-整理前
標記-整理後
從上圖可以看出,使用標記整理演算法後記憶體是規整的,解決了標記-清除演算法中記憶體碎片的問題,但是多了一個記憶體整理的過程。
分代演算法
分代演算法,其實不能算是一個垃圾回收的演算法,可以理解為一種垃圾回收的方案,即把記憶體分為不同的塊也即代,每一塊使用不同的垃圾回收演算法。現代主流的垃圾回收器都是使用分代的思想,如下圖
上圖即是分代演算法的示意圖,把堆區分為新生代和老年代,新生代又分為Eden S0 S1;新生代使用複製演算法,老年代使用標記-清除/標記-整理演算法。
有不當之處,歡迎指正,謝謝