GC四大記憶體回收演算法
阿新 • • 發佈:2019-01-11
- 堆
- 新生代
- Eden 伊甸園
- Survivor 存活區
- Tenured Gen 退休區
- 老年代
- 新生代
- 方法區
- 棧,本地方法棧 程式計數器
1、標記清除法
根據被標記的垃圾物件,逐個進行清理。效率高,但是清理回收後,導致記憶體不連續,形成記憶體碎片。此時如果有新物件需要消耗更大的記憶體,雖然總空閒記憶體足夠,由於記憶體不連續,會導致建立失敗。為了解決這個缺陷,故而衍生了下面的複製法。
2、複製法
將可用的記憶體按容量劃分為大小相等的兩塊(from,to)。每次把沒有被標誌的,即倖存的物件複製到一邊去(to),然後把(from)這塊記憶體格式化的清理。這樣子就能保證被清理的記憶體總是連續可用的。然而,每次只是用其中一塊(總有一塊是空的【to區域】),造成了記憶體的使用率折半。
針對記憶體使用率問題底下,複製演算法又繼續衍生出下面的不均分的三塊記憶體區,其中Eden區佔據最大
第二次GC:
新生代的倖存區(Survivor)保持的是上一次Eden區中被保留的物件和上一次另一個Survivor副本里面保留的物件。兩個Survivor區做常規的複製演算法,Eden區與當前被選為備份的Survivor區做複製演算法。Eden區是新生代最開始的一個區域,每次GC光顧後,10%的物件是存活的,把這10%的物件複製後,清空Eden區,重新得到大塊的Eden可用記憶體。故而記憶體的使用率由50%提高到了80%,
但是對於倖存區(survivor),90%都是仍然存活的,那麼每次都要去遍尋複製會造成效能的浪費。
3、標記整理法
標記:
整理:把被標記的垃圾物件移動到記憶體的末端,統一回收。
標記整理演算法主要是針對Survivor區記憶體回收的,它的“標記”過程和標記-清除演算法一致,只是後面並不是直接對可回收物件進行整理,而是讓所有垃圾物件都向末端移動,然後直接清理掉端邊界意外的記憶體。由於標記後繼續整理,可以很明顯的看出未使用的地址空間都是連續的,不會產生記憶體碎片。而且不需要複製倖存物件,針對Survivor區,大量物件都是倖存的,可以有效避免重複的複製工作導致效能的浪費。
4、分代收集法
其實分代收集法並不是一個新的演算法,只是整合了複製演算法和標記整理演算法,管理它們。針對不同的記憶體區域,根據這些記憶體區域的特性使用不同的演算法(選擇複製法還是標記整理法)。例如,在新生代中的Eden區,物件的存活率是非常低的,這裡被採用複製演算法;在老年代記憶體區,存活率超級高,這裡會採用標記整理演算法。
以上是本人對GC各收集演算法的淺薄理解,沒有經過強有力的論證,有不足之處還望多多指教!