在深刻GC算法的實現細節以前,咱們最好先來了解下相關術語及背後的基本原理。不一樣回收器的實現細節各有不一樣,但總的來講基本全部的回收器都會關注以下兩個方面:html
首先,全部回收器都會經過一個標記過程來對存活對象進行統計。算法
JVM中用到的全部現代GC算法在回收前都會先找出全部仍存活的對象。下圖中所展現的JVM中的內存佈局能夠用來很好地闡釋這一律念:安全
首先,垃圾回收器將某些特殊的對象定義爲GC根對象。所謂的GC根對象包括:佈局
接下來,垃圾回收器會對內存中的整個對象圖進行遍歷,它先從GC根對象開始,而後是根對象引用的其它對象,好比實例變量。回收器將訪問到的全部對象都標記爲存活。spa
存活對象在上圖中被標記爲藍色。當標記階段完成了以後,全部的存活對象都已經被標記完了。其它的那些(上圖中灰色的那些)也就是GC根對象不可達的對象,也就是說你的應用不會再用到它們了。這些就是垃圾對象,回收器將會在接下來的階段中清除它們。線程
關於標記階段有幾個關鍵點是值得注意的:指針
當標記階段完成後,GC開始進入下一階段,刪除不可達對象。htm
不一樣的GC算法在刪除無用對象上的作法會有所不一樣,不過大體上能夠爲分三類:清除(Sweeping),整理/壓縮(Compacting)以及拷貝(Copying)。下面的幾節將會詳細介紹下這幾種算法的不一樣。對象
清除內存
從概念上來說,標記-清除算法使用的方法是最簡單的,只須要忽略這些對象即可以了。也就是說當標記階段完成以後,未被訪問到的對象所在的空間都會被認爲是空閒的,能夠用來建立新的對象。
這種方法須要使用一個空閒列表來記錄全部的空閒區域以及大小。對空閒列表的管理會增長分配對象時的工做量。這種方法還有一個缺陷就是——雖然空閒區域的大小是足夠的,但卻可能沒有一個單一區域可以知足此次分配所需的大小,所以本次分配仍是會失敗(在Java中就是一次OutOfMemoryError)。
整理
標記-清除-整理算法修復了標記-清除算法的短板——它將全部標記的也就是存活的對象都移動到內存區域的開始位置。這種方法的缺點就是GC暫停的時間會增加,由於你須要將全部的對象都拷貝到一個新的地方,還得更新它們的引用地址。相對於標記-清除算法,它的優勢也是顯而易見的——通過整理以後,新對象的分配只須要經過指針碰撞便能完成(pointer bumping),至關簡單。使用這種方法空閒區域的位置是始終可知的,也不會再有碎片的問題了。
複製
標記-複製算法與標記-整理算法很是相似,它們都會將全部存活對象從新進行分配。區別在於從新分配的目標地址不一樣,複製算法是爲存活對象分配了另外的內存區域做爲它們的新家。標記複製算法的優勢在於標記階段和複製階段能夠同時進行。它的缺點是須要一塊能容納下全部存活對象的額外的內存空間。
原創文章轉載請註明出處:GC算法基礎