複製演算法就是將記憶體空間二等分, 每次只使用其中一塊. 當執行gc時, 講a部分的所有活動物件集體移到b中, 就可以講a全部釋放.
畫個圖就是:
在執行gc前, 記憶體長這樣:
當執行gc後, 記憶體就變成這樣了:
還記得標記清除演算法
的問題是什麼嗎? 記憶體碎片化嚴重. 現在好了, 碎片化問題解決了, 每次gc執行後, 記憶體空間都是連續的啦.
想一想gc執行的步驟是什麼? 很簡單啊, 遍歷所有可訪問的物件, 將所有物件的複製到另一塊記憶體中. 完畢.
遍歷所有根集合的物件, 跳過. 將每個物件都呼叫一次copy函式, 那麼, 這個copy函式如何實現呢?
function copy
(obj)
// 這裡假設有乙個全域性變數 addr 指向空閒記憶體的首位址
// 這裡直接將 obj的size大小複製到addr的地方
copy_data
(addr, obj, obj.size)
;// 記錄複製
obj.iscopy = true;
obj.newaddr = addr;
// 更新空閒位址
addr +
= size;
// 將所有子物件複製
for(child in children)
return obj.newaddr;
}
將所有根集合中的物件依次呼叫copy函式, 完成複製.
複製演算法分配新的物件變簡單了, 有沒有? 因為位址都是連續的, 所以申請新的位址也不用遍歷鍊錶等一堆操作, 直接按著位址劃分空間就行了.
很明顯,複製演算法
解決了標記清除
的乙個大問題, 記憶體碎片化嚴重. 在這裡, 根本不存在碎片化問題的好嘛. 其相比標記清除
的優勢還是有一些的:
記憶體不會發生碎片化最大暫停時間更短:複製演算法
只需要遍歷所有的活動物件, 而不需要遍歷堆, 比標記清除
要少乙個堆的遍歷, 故而執行更快.
記憶體分配高效:標記清除
是怎麼分配記憶體的? 通過乙個空閒位址的鍊錶, 然後挨個找. 而複製演算法
將所有可分配的記憶體都放到一起了, 直接切割即可.
更好的區域性訪問:複製演算法
複製後將物件與子物件放到一起, 這樣快取在讀取的時候就能夠一起讀取, 防止多次讀取資料.
當然, 缺點也很明顯. 將堆一分為二, 使用效率急速下滑.
堆的使用效率低, 只有1/2
頻繁的遞迴呼叫函式. 對棧的壓力比較大, 但是我們都知道, 所有用遞迴能寫的都可以換成迴圈來實現, 所以個人感覺這個並不是問題.
我看到有一種多空間複製演算法
, 為了提高堆的使用效率. 將堆空間分成n份, 其中的兩份使用複製演算法
, 剩餘的使用其他方法執行gc. 我實在是沒有明白這麼做的好處在哪…
GC複製演算法
gc複製演算法 它是把某一空間的活動物件全部複製到另乙個空間,複製完成後gc也就結束了 一起看下gc複製演算法的copying函式 copying copy函式在複製時會先檢查是否已被複製,若已被複製,不再操作,否則進行複製,貼上copied標籤複製完成返回新空間的位址,這樣即使有多個物件引用obj...
GC演算法 筆記 GC標記 壓縮演算法
將 gc標記 清除演算法與gc複製演算法相結合。一 lisp2演算法 標記階段結束後進入壓縮階段,壓縮階段縮小被標記節點之間的距離。compaction phase set forwarding ptr adjust ptr move obj 優點 可有效利用堆 缺點 壓縮花費計算成本 二 two ...
GC常用演算法
jvm在進行gc時,並不是對這三個區域統 一 大部分時候,都是新生代 新生代 倖存區 form,to 老年區 gc兩種類 輕gc 普通的gc 重gc 全域性gc 倖存區的from和to是動態變化的,誰空誰是to gc常用演算法 引用計數器演算法 原理 此物件有乙個引用,則 1 刪除乙個引用,則 1。...