停止和復制
標記和清除法的兄弟就是停止和復制收集法了
停止和復制法解決了標記和清除法的碎片問題
但是對內存提出了更高的要求(或者是對一個較小的對象池進行更加頻繁的收集)
微軟的Java虛擬機使用的就是這個算法
而在當時這是最快的虛擬機之一
停止和復制法的原理是為對象創建兩個內存池
但是每次只使用其中的一個
在你分配對象的時候
它就簡單地在活動的內存池中為你指定下一個可用空間
如果內存池填滿了——或者如果系統決定該收集了——它就進行同標記和清除法相同動作
跟蹤程序裡系統對象的所有指針
但是不僅僅標記這些對象
它把它們從當前的內存池裡復制到另一個非活動的內存池裡
這個復制動作將活動著的對象一個一個安置到新的內存池裡
一完成這個過程
它就將原來這個原本非活動的內存池切換成活動的
由於它只復制活動的對象
所以垃圾對象被留了下來
要收集的總是會比要扔掉的少
復制這一過程事實上整理了新的內存池
因為對象是一個接一個放置的
停止和復制法仍然必須要停止正在運行的程序
以收集對象並把它們移到內存池裡
在這個算法運行的時候
它在清理的應用程序會停下來
導致程序的波動
世代
活動垃圾收集法的輪廓揭示了一些基礎性錯誤
這些錯誤在垃圾收集算法如何工作同垃圾需要如何被收集比較時產生
正在運行的應用程序的大多數對象只會存活很短的時間
只有極少數會存活在應用程序運行的全過程中
前面勾畫的算法平等地處理所有對象
不幸的是
每個活動的對象都需要被處理(例如移動
標記)
這會對性能造成負面影響
長時間存活的對象是持續的——所以不需要——在每次收集時被移來移去
當前
像最新的Java Hotspot虛擬機裡使用的垃圾收集程序分別為新老對象創建各自的內存池
這樣的新老對象叫做
代
如果一個對象經歷了特定的收集次數(有的時候就一次
但是次數依賴於收集程序)
它就被從新內存池移到老內存池裡
老內存池
從本質上講
收集的次數會更少
這樣考慮的原因是
既然這些對象已經存活了一段時間了
它們會存活得更長
這樣就大大降低了垃圾收集程序的負載
一輪收集過程中就結束的短時間存活對象對收集程序的影響較小
因為收集程序主要對存活的對象進行處理
對老一代對象的收集要少得多
這就減少了對老對象不必要的移動
不同的代甚至可以有不同的算法來處理它們
例如
停止和復制法適用於新對象池
因為它認為新對象結束得更快(對於非垃圾對象而言
停止和復制法的性能耗費是線性的)
對老一代的對象能夠采取額外的步驟以實現更加精確的算法
因為對性能的要求不是問題
好好利用垃圾收集
盡管有各種好處
垃圾收集法仍然會從正在運行的應用程序手中搶奪CPU
要最小化這種影響的最好辦法其實很簡單
少創建對象
更少的對象需要更少收集操作
理論上這會提高性能
垃圾收集是邁向擺脫每日編程中一些難纏細節的堅實步驟
這個問題是過去幾年討論的熱點
現在所使用的技術已經很老了(從計算機領域來看)
所以是該好好利用垃圾收集程序的時候了
From:http://tw.wingwit.com/Article/program/Java/Javascript/201311/25425.html