常用的垃圾回收算法有如下四種:標記-清除、復制、標記-整理和分代收集。
標記-清除算法
從算法的名稱上可以看出,這個算法分為兩部分,標記和清除。首先標記出所有需要被回收的對象,然后在標記完成后統一回收掉所有被標記的對象。
這個算法簡單,但是有兩個缺點:一是標記和清除的效率不是很高;二是標記和清除后會產生很多的內存碎片,導致可用的內存空間不連續,當分配大對象的時候,沒有足夠的空間時不得不提前觸發一次垃圾回收。
復制算法
這個算法將可用的內存空間分為大小相等的兩塊,每次只是用其中的一塊,當這一塊被用完的時候,就將還存活的對象復制到另一塊中,然后把原已使用過的那一塊內存空間一次回收掉。這個算法常用於新生代的垃圾回收。
復制算法解決了標記-清除算法的效率問題,以空間換時間,但是當存活對象非常多的時候,復制操作效率將會變低,而且每次只能使用一半的內存空間,利用率不高。
標記-整理算法
這個算法分為三部分:一是標記出所有需要被回收的對象;二是把所有存活的對象都向一端移動;三是把所有存活對象邊界以外的內存空間都回收掉。
標記-整理算法解決了復制算法多復制效率低、空間利用率低的問題,同時也解決了內存碎片的問題。
分代收集算法
根據對象生存周期的不同將內存空間划分為不同的塊,然后對不同的塊使用不同的回收算法。一般把Java堆分為新生代和老年代,新生代中對象的存活周期短,只有少量存活的對象,所以可以使用復制算法,而老年代中對象存活時間長,而且對象比較多,所以可以采用標記-清除和標記-整理算法。