1、引用計數器算法(廢棄)
引用計數器算法是給每個對象設置一個計數器,當有地方引用時計數器+1,引用失效時計數器-1,計數器爲0時就垃圾回收。
特點:引用計數器實現簡單,效率高,但不能解決循環引用問題--每個對象生成獨立的計數器。
2、根搜索算法(使用)
根搜索算法是通過一些"GC Roots"對象作爲起點,從這些節點開始往下搜索,搜索通過的路徑成爲有引用鏈,當一個對象沒有被GC Roots的引用鏈鏈接的時候,說明這個對象就垃圾回收。
GC Roots對象包括:
a)虛擬機棧(棧幀中的本地變量表)中的引用對象。
b)方法區域中的類靜態屬性引用的對象。
c)方法區域中常量引用的對象。
d)本地方法棧中JNI(Native方法)的引用對象。
通過上面的算法搜索到無用對象之後,就是垃圾回收過程,回收算法如下:
1)標記--清除算法(Mark-Sweep)
標記清除算法包括兩個階段:"標記"和"清除"。在標記階段,通過"GC Roots"搜索可達到的對象,並做標記(存活)。清除階段"GC Roots"搜索不可達到的對象進行清除。標記清除算法是標記整理、複製算法的基礎的收集算法,標記和清除階段的效率不高,因爲清除後會產生大量不連續的空間,這就當程序需要分配大內存對象時,可能無法找到足夠的連續空間。
2)複製算法(Copying)
複製算法是把內存分成大小相等的兩塊,每次使用其中一塊,當垃圾回收的時候,把存活的對象複製到另一塊上,然後把這塊內存整個清理掉。複製算法實現簡單,運行效率高,但由於每次只能使用其中的一半就會造成內存的利用率不高(對象少時)。現在的JVM用複製方法收集新生代,由於新生代中大部分對象(98%)都是朝生夕死的,所以存活率較高。
3)標記--整理算法(Mark-Compact)
標記整理算法和標記清除算法相似,但標記算法不是把存活對象複製到另一塊內存,而是把存活的對象往內存的一端移動,然後直接回收邊界以外的內存。標記整理算法提高了內存的利用率,並且它適合在收集對象存活時間較長的老年代。
4)分代收集(Generational Collection)
分代收集是根據對象的存活時間把內存分爲新生代和老年代,根據各個代對象的存活特點,每個代採用不同的垃圾回收算法。新生代採用複製算法,老年代採用標記整理算法。垃圾算法的實現涉及大量的程序細節,而且不同的虛擬機平臺實現的方法也各不相同。
參照來源:《黑馬程序員面試寶典(java).pdf》