在現(xiàn)行的垃圾回收算法中主要有以下幾種:
1.標記-清除算法
標記-清除算法是最基本的算法串稀,后續(xù)的算法都是在這個基礎上對其不足進行改進而得到的。
這個算法主要分為兩步:1 標記所有活動的對象擎椰;2? 清除已經(jīng)死亡的對象(標記了的是活動的對象,未標記的就是可清除的對象)
第一步 :標記所有活動的對象? (另一種說法是標記所有需要回收的對象芯勘,無論是哪一種缰犁,其原理是一致的)
標記使用的是 深度優(yōu)先遍歷 (根 -左-右),原因是內(nèi)存使用量要比 廣度優(yōu)先遍歷 (層次遍歷)要小捡偏。
具體實現(xiàn):首先要標記根直接引用的對象唤冈,然后進行遞歸,偽代碼就是:
mark(obj){
? ? ? ? if(obj.mark == FALSE)//如果沒有標記
? ? ? ? ? ? ? obj.mark =TRUE //則設置為標記
? ? ? ? for(child : children(obj))//遞歸處理子對象
? ? ? ? ? ? ? mark(*child)
}
判斷對象是否存活用的是前面介紹過的 對象的可達性分析
第二步:清除所有沒有標記的對象
在這一步银伟,我們遍歷整個java堆你虹,按順序一個一個的遍歷對象的標記標志位
1.設置了標志位的,表示是存活的對象彤避,將標志位設為false傅物,為下一次GC 的標記 做準備
2.沒有設置標志位的,表示當前對象已經(jīng)可以回收
該回收算法的優(yōu)缺點
1.優(yōu)點:算法簡單琉预,實現(xiàn)容易
2 缺點:一個是效率不高董饰。二個是內(nèi)存碎片化。在標記清除之后會產(chǎn)生大量的不連續(xù)的內(nèi)存碎片圆米,空間碎片太多會導致在需要分配較大的對象時卒暂,無法找到足夠連續(xù)的內(nèi)存而不得不提前觸發(fā)下一次GC。
3.標記-清除 算法使用的時空閑鏈表
后面的算法均時根據(jù)該算法的缺點進行改進而衍生出來的
2.復制算法
原理:將可用內(nèi)存分為大小相等的兩塊娄帖,每次使用其中一塊也祠,當使用的那一塊內(nèi)存用完后,將存活的對象復制到另一塊上块茁,然后一次性清理掉用完的那塊空間齿坷,如此往復桂肌。
這樣設計的目的時為了 解決效率問題,實現(xiàn)了傳統(tǒng)意義上的空間換時間永淌。
復制算法執(zhí)行時分為三個重要步驟
1.標記存活對象
2.拷貝存活對象(已經(jīng)標記的對象)到新的內(nèi)存區(qū)域崎场,并更新對象指針。
3.一次性清理已使用的內(nèi)存空間
復制算法的優(yōu)點
優(yōu)點 :實現(xiàn)簡單遂蛀,運行高效谭跨,不會發(fā)生內(nèi)存碎片化(移動指針,按序分配內(nèi)存)
缺點:內(nèi)存使用率低下(將內(nèi)存一分為二李滴,每一次只有一半的內(nèi)存可用),存活對象較多時螃宙,效率同樣不高
由于最原始的算法內(nèi)存使用率太低,后來的商業(yè)虛擬機在這基礎上有一定的改進所坯。
在新生代中的對象98%的對象是“朝生夕死”谆扎,所以并不需要以1:1 的比例來分配 from 與 To 的空間,而是將內(nèi)存分為一塊較大的Eden空間跟兩塊較小的 Survivor空間(HotSpot中默認的時8:1:1)芹助,每次使用的是Eden與其中的一塊Survivor空間堂湖。當回收時,將存活的對象復制到另一塊Survivor空間上状土,最后清理掉Eden與survivor空間无蜂,這樣能使用的內(nèi)存空間就大大提高了。
如果剩下的Survivor空間不夠存放存活的對象蒙谓,就需要依賴其他內(nèi)存來進行分配擔保了,這些對象會直接通過分配擔保機制直接進入老年代累驮。
3.標記-整理算法 (又稱標記-壓縮算法)
標記-整理算法時在標記-清除算法上的一種改進酣倾。整理不會改變對象排列的順序,只會縮小他們之間的間隙慰照,把對象聚集到堆的一端灶挟。
標記階段與前面的分析沒有什么區(qū)別,整理壓縮主要有以下三個步驟:
1.設定forwarding 指針
2.更新指針
3.移動對象
標記-整理算法的優(yōu)缺點
優(yōu)點:java堆的利用得到進一步的提高
缺點:整理是一個移動對象的過程毒租,伴隨著對象的移動以及指針的修改,這也是一筆不小的開銷
4.分代收集算法
這是現(xiàn)在主流的商業(yè)虛擬機采用的垃圾回收算法箱叁,其主要思想是將Java堆分為 新生代 與 老年代墅垮。
對新生代采用一般采用復制算法(大量的對象死亡,回收效率比較高)耕漱,對老年代就必須使用標記-清除或者標記-整理算法來進行回收
優(yōu)缺點
優(yōu)點:效率明顯提升
缺點:新生代GC所花費的時間會增多算色,老年代GC會頻繁運行。
現(xiàn)在常使用的垃圾收集器有如下幾種
1.serial收集器? ? (新生代 單線程? 復制算法)
jdk1.3.1之前是新生代收集的唯一選擇
這是以一個單線程的收集器螟够,它工作時會暫停其他所有的工作線程 也就是著名的 Stop- The -World
優(yōu)點:由于是單線程灾梦,所以沒有線程之間的切換開銷
缺點:在其工作時會停止所有其他工作線程
2.ParNew 收集器? (serial的多線程版本) 新生代? 多線程? 復制算法
在單CPU的環(huán)境下峡钓,其效率還不如Serial收集器
3.Parallel Scanvenge 收集器? (新生代 多線程? 復制算法)
這個收集器關注的不是系統(tǒng)停頓的時間,而是達到一個可以控制的吞吐量
4.Serial Old收集器 (老年代 單線程? 標記-整理算法)
5.Paralle Old 收集器 (老年代 多線程 標記-整理算法)
關注點:吞吐量
6.CMS收集器 Concurrent Mark Sweep(老年代 多線程 標記-清除算法)
關注點:獲取最短回收停頓時間為目標的收集器
CMS收集器工作流程分為四個步驟
1.初始標記//stop the world 標記以下GC Roots能關聯(lián)到的對象
2.并發(fā)標記// 標記GC Roots之后的對象
3.重新標記//stop the world 修正并發(fā)期間用戶程序繼續(xù)運行產(chǎn)生變動的那一部分對象的標記記錄
4.并發(fā)清除
這是一款真正意義上的 并發(fā) 垃圾收集器
缺點
1.對CPU資源非常敏感
2.無法處理浮動垃圾(垃圾收集的過程中若河,應用程序運行產(chǎn)生的其他垃圾)
3.因為時基于標記-清除算法能岩,所以依舊會產(chǎn)生大量的內(nèi)存碎片
7.科技的最前沿 G1收集器
G1的優(yōu)點有以下幾點:
1.并行與并發(fā)
2.分代收集
3.基于標記-整理算法,會對空間進行進一步的整合
4.Stop-The-World 的時間可以預測