分爲「標記」和「清除」兩個階段。首先標記出全部須要回收的對象,在標記完成後統一回收全部被標記的對象。 存在如下兩個問題:git
將內存劃分爲大小相等的兩塊,每次只使用其中一塊,當這一塊內存用完了就將還存活的對象複製到另外一塊上面,而後再把使用過的內存空間進行一次清理。github
如今的商業虛擬機都採用這種收集算法來回收新生代,可是並非將新生代劃分爲大小相等的兩塊,而是分爲一塊較大的 Eden 空間和兩塊較小的 Survivor 空間,每次使用 Eden 空間和其中一塊 Survivor。在回收時,將 Eden 和 Survivor 中還存活着的對象一次性複製到另外一塊 Survivor 空間上,最後清理 Eden 和使用過的那一塊 Survivor。算法
HotSpot 虛擬機的 Eden 和 Survivor 的大小比例默認爲 8:1,保證了內存的利用率達到 90%。若是每次回收有多於 10% 的對象存活,那麼一塊 Survivor 空間就不夠用了,此時須要依賴於老年代進行分配擔保,也就是借用老年代的空間存儲放不下的對象。jvm
根據老年代的特色特出的一種標記算法,標記過程仍然與「標記-清除」算法同樣,但後續步驟不是直接對可回收對象回收,而是讓全部存活的對象向一端移動,而後直接清理掉端邊界之外的內存。cdn
如今的商業虛擬機採用分代收集算法,它根據對象存活週期將內存劃分爲幾塊,不一樣塊採用適當的收集算法。對象
通常將堆分爲新生代和老年代。在新生代中,每次收集都會有大量對象死去,因此能夠選擇複製算法,只須要付出少許對象的複製成本就能夠完成每次垃圾收集。而老年代的對象存活概率是比較高的,並且沒有額外的空間對它進行分配擔保,因此咱們必須選擇標記-清除或標記-整理算法進行垃圾收集。blog
參考資料內存