之前談到的所有算法都是內存回收的理論基礎敢课,而現在我們來談談關于內存回收的具體實現。
垃圾收集器分為七種:Serial 收集器,ParNew 收集器震捣,Parallel Scavenge 收集器,Serial Old 收集器闹炉,Parallel Old 收集器蒿赢,CMS 收集器,G1 收集器渣触。
下圖展現了這七種作用于不同分代的垃圾收集器诉植,存在連線代表可以搭配使用。
接下來我們依次了解一下各垃圾收集器昵观。
(1)Serial收集器
最基本的晾腔,發(fā)展歷史最悠久的單線程垃圾收集器,曾是(JDK1.3之前)虛擬機新生代收集器唯一選擇啊犬。因簡單高效(相對于其它的單線程收集器)灼擂,沒有多余的線程開銷,在Client模式下是一個非常好的選擇觉至。
缺點:在它工作時必須暫停其它所有的線程(服務暫停)剔应,直到Serial收集器將所有垃圾收集完成,因此可能會產生較長的等待時間语御。
新生代峻贮、老年代使用串行回收;新生代復制算法应闯、老年代標記-整理算法纤控。
參數控制: -XX:+UseSerialGC 指定使用Serial垃圾收集器
Serial收集器運行示意圖
(2)ParNew收集器
Serial收集器的多線程版本,其余行為都與Serial收集器完全一致碉纺,兩者其實共用了大量相同的代碼船万。除了Serial收集器外刻撒,唯一一個能與CMS收集器配合工作的收集器,在Server模式下的虛擬機中首選的新生代收集器耿导。ParNew收集器在單CPU的環(huán)境中絕對不會比Serial收集器有更好的效果声怔。
ParNew收集器運行示意圖大致一樣
參數控制:
-XX:+UseParNewGC 強制指定ParNew收集器
-XX:ParallelGCThreads 限制線程數量
(3)Parallel Scaveng收集器
新生代收集器,也是復制算法的收集器舱呻,且還是并行的多線程收集器醋火。其他的垃圾回收器都是關注如何縮短在垃圾回收時用戶線程的等待時間,而Parallel Scavenge收集器則是關注系統(tǒng)吞吐量:吞吐量=運行用戶代碼的時間/(運行用戶代碼的時間+垃圾收集時間)箱吕。吞吐量越高越能代表高效率的利用CPU胎撇,因此也被稱為“吞吐量優(yōu)先”收集器。
Parallel Scavenge收集器與ParNew收集器的主要區(qū)別是前者擁有GC自適應的調節(jié)策略(GC Ergonomics)殖氏,由參數-XX:+UserAdaptiveSizePolicy控制晚树。
參數控制:
-XX:+UseParallelGC:使用Parallel收集器+ 老年代串行
-XX:MaxGCPauseMillis:最大垃圾回收停頓時間,一個大于0的毫秒數雅采。該值不是越小越好爵憎,GC停頓時間是以犧牲吞吐量與新生代空間換取的。
-XX:GCTimeRatio:直接設置吞吐量大小婚瓜,大于0小于100的整數宝鼓,垃圾回收時間占總時間的比率,相當于吞吐量的倒數巴刻,比如設置為9愚铡,那么就是1/(1+9),最大GC時間就占總時間的10%胡陪。
-XX:+UserAdaptiveSizePolicy:開關參數沥寥,開啟后就會自動根據系統(tǒng)當前的性能信息,動態(tài)調整新生代大小柠座,Eden和Survivor比例邑雅,晉升老年代對象大小等參數。
Parallel Scaveng收集器運行示意圖
(4)Serial Old收集器
作為Serial收集器的老年代版本妈经,同樣是一個單線程收集器淮野,主要給Client模式下的虛擬機使用,在Server模式下有兩大用途:①在JDK1.5及之前的版本中與Parallel Scavenge收集器搭配使用吹泡;②作為CMS收集器的備選方案骤星,在并發(fā)收集發(fā)生 Concurrent Mode Failure 時使用。
Serial Old收集器運行示意圖
(5)Parallel Old收集器
Parallel Old是Parallel Scavenge收集器的老年代版本爆哑,使用多線程和“標記-整理”算法洞难。這個收集器是在JDK 1.6中才開始提供。在注重吞吐量與CPU資源敏感的場合泪漂,都可以優(yōu)先考慮 Parallel Scavenge收集器加Parallel Old收集器的組合
參數控制: -XX:+UseParallelOldGC 使用Parallel收集器+ 老年代并行
Parallel Old收集器運行示意圖
(6)CMS收集器
CMS(Concurrent Mark Sweep)收集器是一種以犧牲吞吐量為代價獲取最短回收停頓時間為目標的收集器廊营。在重視服務的響應速度,希望系統(tǒng)停頓時間最短的情況下使用該收集器是最佳的選擇萝勤。CMS是用于對年老代的回收露筒,利用和應用程序線程并發(fā)的垃圾回收線程來標記清除年老代。
CMS收集器是基于“標記-清除”算法實現的敌卓,CMS收集器的GC周期由6個階段組成慎式。其中4個階段與實際的應用程序是并發(fā)執(zhí)行的,而其他2個階段需要暫停應用程序線程趟径。:
①初始標記(CMS initial mark):執(zhí)行時必須暫停其他一切線程(官方稱為:Stop The World)瘪吏,僅僅只是標記一下GC Roots能直接關聯(lián)到的對象,速度很快蜗巧。
②并發(fā)標記(CMS concurrent mark):這個動作發(fā)生在進行GC Roots Tracing的過程中掌眠,緊隨初始標記階段,耗時較長幕屹,但由于應用程序的線程和并發(fā)標記的線程并發(fā)執(zhí)行蓝丙,所以用戶不會感覺到停頓。
③并發(fā)預清理(CMS concurrent precleaning):在并發(fā)標記階段可能有新進入老年代的對象望拖,并發(fā)預清理就是查找這些新對象以減少下一步的負擔渺尘。
④重新標記(CMS remark):執(zhí)行時也必須暫停其他一切線程。為了修正并發(fā)標記期間说敏,因用戶程序繼續(xù)運作而導致標記產生變動的那一部分對象的標記記錄鸥跟,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比并發(fā)標記的時間短盔沫。
⑤并發(fā)清除(CMS concurrent sweep):清理垃圾對象医咨,這個階段收集器線程和應用程序線程并發(fā)執(zhí)行,耗時較長架诞。
⑥并發(fā)重置(CMS concurrent reset):重置CMS收集器的數據結構腋逆,等待下一次的垃圾回收執(zhí)行。
CMS收集器運行示意圖
優(yōu)點:并發(fā)收集侈贷,低停頓
缺點:
①對CPU資源非常敏感惩歉,在并發(fā)階段可能會導致系統(tǒng)吞吐量下降。
②在CMS并發(fā)清理階段用戶線程也在運行俏蛮,用戶線程就會產生新的垃圾撑蚌,這部分垃圾在被標記后會被延遲到下一次GC時才被清理掉,這一部分垃圾就叫做“浮動垃圾”搏屑。在CMS收集器會預留一部分空間給用戶線程使用争涌,當預留空間不足時就會導致“Concurrent Mode Failure”失敗。所以當CMS收集器無法處理浮動垃圾時辣恋,空間不足可能導致“Concurrent Mode Failure”失敗而導致另一次的 Full GC的產生亮垫。
③CMS收集器是基于“標記-清除”算法實現的模软,所以收集結束時可能會產生大量的空間碎片,可以通過參數設置碎片整理饮潦。
參數
-XX:+UseConcMarkSweepGC:使用CMS收集器
– XX:CMSInitiatingOccupancyFraction =n :CMS收集器的啟動閥值燃异,該值代表老年代空間已使用的比例。該值太高可能會導致無法預留足夠的空間給用戶線程继蜡,從而導致“Concurrent Mode Failure”失敗回俐。
-XX:+ UseCMSCompactAtFullCollection:Full GC后,進行一次碎片整理稀并;整理過程是獨占的仅颇,會引起停頓時間變長
-XX:+CMSFullGCsBeforeCompaction 設置進行幾次Full GC后,進行一次碎片整理
-XX:ParallelCMSThreads 設定CMS的線程數量(一般情況約等于可用CPU數量)
(7)G1收集器
面向服務端應用的碘举,基于“標記-整理”算法實現的垃圾收集器忘瓦,在JDK1.7u4版本及以后才作為正式的商用,在未來準備替換掉JDK1.5中發(fā)布的CMS收集器引颈。
與其他收集器相比政冻,G1具備以下優(yōu)勢:
①并行與并發(fā):通過多核與多CPU優(yōu)勢,縮短系統(tǒng)停頓時間线欲,且不影響Java程序的執(zhí)行明场。
②分代收集:G1不需要與其他收集器配合就能獨立管理整個GC堆。
③空間整合:不會產生空間碎片李丰。
④可預測的停頓:區(qū)別于CMS苦锨,G1最大的優(yōu)勢就是可以系統(tǒng)停頓時間可控可預測。
對垃圾收集器的總結
不再將老年代與新生代進行物理隔離趴泌,而是將堆規(guī)劃為大小相等的獨立區(qū)域(Region)劃分內存空間舟舒。根據垃圾的堆積的價值大小,G1會在后臺維護一個優(yōu)先列表嗜憔,優(yōu)先回收垃圾價值最大的區(qū)域秃励。
G1收集器的步驟分為以下四個步驟:
①初始標記(Initial Mark):執(zhí)行時必須暫停其他一切線程(官方稱為:Stop The World)俐末,標記一下GC Roots能直接關聯(lián)到的對象浑测,并且修改TAMS值,讓下一階段用戶程序并發(fā)執(zhí)行時能夠在正確的區(qū)域進行創(chuàng)建對象姚建,執(zhí)行速度很快呐舔。
②并發(fā)標記(Concurrent Marking):從GC Roots開始對堆中對象進行可達性分析币励,耗時間長,但可以與用戶線程并發(fā)執(zhí)行珊拼。
③最終標記(Final Marking):執(zhí)行時也必須暫停其他一切線程食呻。為了修正并發(fā)標記期間,因用戶程序繼續(xù)運作而導致標記產生變動的那一部分對象的標記記錄。
④篩選回收(Live Data Counting and Evacuation):對各個區(qū)域(Region)的回收價值與成本排序仅胞,然后根據用戶指定的GC停頓時間來制定回收計劃每辟。
參數
-XX:+UseG1GC :啟動GC收集器
-XX:G1HeapRegionSize : 設定堆中區(qū)域(Region)的大小,大小區(qū)間只能是2的冪次方
對垃圾收集器的總結