常用的垃圾收集器
截至目前為止,並沒有一種完美的垃圾回收器或者說沒有萬能的回收器。我們只能比較各個垃圾收集器的優勢與不足,根據具體的業務場景選擇和業務最為接近的垃圾收集器。常用的垃圾回收器如下:
Serial收集器:開啟引數為-XX:+UseSerialGC -XX:+UseSerailOldGC,Serial為序列的垃圾收集器,Serial進行垃圾收集時,只會開啟一條垃圾收集程序,並暫停其他所有的程序 去進行垃圾清理工作。優勢:簡單高效,沒有執行緒之間的互動,單執行緒的收集效率非常高使用:有點真正意義上的"Stop The World"的感覺,一般此收集器都是和其他收集器搭配使用 ,或者作為CMS收集器的備選方案回收演算法:新生代採用複製演算法,老年代採用標記整理演算法ParNew收集器:開啟引數為 -XX:UseParNewGC ,parnew收集器簡單上來說就是serial收集器的多執行緒版本,除了利用多執行緒進行垃圾回收外,其餘的回收演算法、收集演算法等方面都是和serial一致優勢:在記憶體空間較大時(執行緒之間的切換開銷遠低於多執行緒垃圾回收節約的時間)比searial更高效地進行垃圾回收使用:一般配合CMS收集器使用Parallel Scavenge收集器:開啟引數為 -XX:+UseParallelGC,parallel scavenge收集器垃圾收集方式和parnew差不多,不過parallel scavenge收集器在利用CPU的效率上比起parnew有一個非常大的提高,即吞吐量上有一個質的提升吞吐量:CPU中執行使用者程式碼所消耗的時間與CPU總消耗量時間的比值優勢:提供了非常多的引數幫助使用者找到最大吞吐量,如果比較關注吞吐量,parallel scavenge是一個不錯的選擇回收演算法:新生代採用複製演算法,老年代採用標記整理演算法Parallel Scavenge收集器工作示意圖
CMS收集器(重點):開啟引數為 -XX:+UseConcMarkSweepGC,此收集器的設計目的是為了縮短gc造成的停頓時間,從而提高使用者的使用體驗。cms收集器的獨特之處在於可以讓垃圾收集執行緒與業務執行緒同時工作,同時cms收集器提供了非常多的引數給開發者,讓cms在不斷的引數最佳化之後,逐步的提高使用者體驗優勢:對垃圾進行併發收集,使用者執行緒停頓時間短cms收集器回收詳細步驟:初始標記:此階段會暫停所有執行緒,將GC Root直接引用的物件進行標記(這就是cms的聰明之處,只標記GC Root直接引用的物件,而不是將和GC Root有關聯的像全部收集,大大降低了物件標記時間)併發標記:此時會同時開啟業務執行緒以及GC執行緒,GC執行緒會將和初始標記物件有關聯的物件全部進行標記,而業務執行緒可以保證業務正常流轉。當然因為此時業務執行緒正常運轉,所以併發標記時無法標記出此期間產生的垃圾物件以及及時的對物件進行可達性分析,不過併發標記演算法會紀律發生引用更新的地方重新標記:此階段會暫停所有執行緒,為了修正併發標記階段因為業務執行緒執行而導致的物件引用更新,不過此階段暫停執行緒的時間相比於併發標記階段的時常來說,非常的短併發清理:開啟業務執行緒,並同步開啟GC執行緒進行垃圾回收cms的缺點:cms的回收步驟不難看出,cms的缺點也比較明顯會和業務執行緒搶佔資源,對CPU資源要求較高併發清理時造成時出現的垃圾無法清理,必須等待下次gc時才能清理回收演算法為“標記-清除”,此演算法會導致大量的記憶體空間碎片,如果需要避免此種情況,可以開啟 -XX:+UseCMSCompactAtFullCollection 引數 讓JVM清除之後對存活的物件進行整理,不過此引數開啟後會略微影響垃圾回收的效率執行過程的不確定性,在併發清理的過程中,因為業務執行緒持續執行,此過程中可能出現再次佔滿老年代空間的情況,如果此情況一旦發生,cms馬上會對jvm進行stop the world,改為serial收集器進行垃圾回收,為了預防此情況的發生,需要在系統執行過程中不斷對CMS引數進行調優,最大可能減低此情況發生。CMS垃圾收集器執行機制
CMS收集器引數:-XX:+UseConcMarkSweepGC:是否開啟cms-XX:ConcGCThreads:cms併發GC執行緒數,此引數不是越大越好,需要根據機器的配置以及具體的業務進行設定-XX:+UseCMSCompactAtFullCollection:full gc後進行記憶體碎片整理,達到減少記憶體碎片的效果-XX:CMSFullGCsBeforeCompaction:當開啟了 UseCMSCompactAtFullCollection 引數後,透過此引數設定,設定多少次full gc後,進行記憶體整理工作,預設值為0,即每次full gc後都會進行碎片整理-XX:CMSInitiatingOccupancyFraction:使用cms收集器,設定觸發full gc 的老年代記憶體佔比閾值,預設為92,即老年代記憶體佔用達到92%就會觸發full gc-UseCMSInitiatingOccupancyOnly:此引數在開啟CMSInitiatingOccupancyFraction引數後生效,因為jvm在每次gc後,會自動調整老年代記憶體閾值,如果此引數開啟,則會一直使用CMSInitiatingOccupancyFraction引數配置的閾值,不會自動調整-XX:+CMSScavengeBeforeRemark:在full gc前開啟一次minor gc
最新評論