常見的垃圾回收器:
-
- Serial
- Serial Old
- Parallel Scavenge
- Parallel Old
- ParNew
- CMS
- G1
- ZGC
- Shenandoah
- Epsilon
下圖已經列出來了這,其中Epsilon是debug使用的,不用過分關注;最常見的組合有:Serial +Serial Old 、Parallel Scavenge + Parallel Old 、ParNew + CMS。G1之前都是不僅在邏輯上是分代的而且在物理層面上也是分代的;G1只是在邏輯上分代;G1之后完全不分代,但是在生產環境使用的很少;
1、Serial
當垃圾收集器工作時所有工作線程全部停止,這里線程停下來一定會停在一個安全點上;
safe-point :線程停止(需要找到一個安全點上線程停止),因為停頓的時間長,現在很少用;
2、Serial Old
這個垃圾收集器用在老年代,它用的是mark-sweep的算法,他用的是單線程;
a stop-the-world
mark-sweep-compact collector that uses a single GC thread(使用單個GC線程的標記-清理-收集器).3、Parallel Scavenge
a stop-the-world
Copying collector which uses multiple GC threads(使用多個GC線程的復制收集器).如果你在JVM沒有做任何的調優的話,默認使用的是:parallel scavenge +parallel old 簡稱(ps + po)
Parallel Scavenge 與Serial的區別:Parallel Scavenge 是多線程清理垃圾,后者為單線程清理垃圾。
4、Parallel Old
a compacting collector that uses multiple GC threads(使用多個GC線程的壓縮收集器).整理算法
5、ParNew
其實就是parallel new 的意思,和Parallel Scavenge沒有很大的區別,就是它的新版本,做了一些的增強以便能夠讓它和CMS有更好的配合使用,CMS在某個特定的階段會和Parallel New 同時運行。在工作的時候其余的線程不能夠工作,必須等GC回收器結束后才可以。
Parallel New 和 Parallel Scavenge 區別:
-
- parallel new 的響應時間優先
- 能夠配合CMS
- parallel scavenge 的吞吐量優先
6、CMS
CMS非常重要,它誕生了一個里程碑,以前的垃圾回收器在工作的時候其他的線程都要停下來,等我工作完,才能工作,CMS的出現消除了這個問題,與此同時CMS也帶來了很多問題,以至於目前的所有的JDK版本默認都不是使用它。
-
- CMS的全拼:concurrent mark sweep
- A mostly concurrent , low-pause collector
- Four phases:
-
- initial mark (初始標記 STW開始標記)
- concurrent mark (並發標記和應用程序同時進行)
- remark (重新標記又是一個STW 在並發標記中產生的新垃圾 在這里進行重新標記 這里是使用多線程)
- concurrent sweep(並發清理的過程中也會產生新的垃圾 這個垃圾叫做浮動垃圾)
6.1、從線程角度理解:
垃圾回收器在工作的時候,垃圾回收的線程和工作線程同時進行,叫做:concurrent mark sweep;當內存比較小的情況下,清理垃圾的速度比較快沒有問題,當內存越來越大較的時候,大到什么程度呢?大到你用多少線程進行清理的都需要很長一段時間,以前10G的內存的時候使用默認的ps+po大概需要的時間為11s。
為什么會出現並發垃圾回收器? 並發垃圾回收器出現的原因是因為忍受不了STW.
6.2、下面來解釋一下CMS常見的幾個階段:
第一個階段叫做CMS initial mark(初始標記階段)這個階段很簡單,就是直接找到最根上的對象,然后進行標記,其他的對象不標記。
第二個階段是CMS concurrent mark(並發標記)據統計百分之八十的時間都浪費在這里,因此它把這塊耗時最長的階段和我們的應用程序同時進行,對於客戶來說感覺上可能慢了點,但是至少還有反應,這里的並發標記是一邊產生垃圾一邊進行跟着標記,這個過程很難完成;
第三階段是CMS remark (重新標記)這里又是一個STW,在上一個並發標記的過程中產生的新垃圾在這個階段進行標記,這個時候需要停頓,但是時間不會很長,畢竟只是上一步很短時間內產生的新垃圾;
第四階段是concurrent sweep(並發清理)並發清理也有他的問題,在並發清理的過程中也會產生新的垃圾,這個垃圾叫做浮動垃圾,這個浮動垃圾就要等下一次CMS來清理了;
什么條件下會觸發CMS呢?老年代分配不下了,這時會觸發CMS,這里的初始標記是單線程,重新標記是多線程。
6.3、CMS的缺點:CMS出現問題后會調用Serial Old使用單線程進行標記壓縮;
CMS的兩大問題:
memory fragmentation 內存的碎片:這個是比比較嚴重的一個問題,如果內存超級大,產生了很多的碎片,這就會浪費很多的空間,其實CMS設計出來就是應付幾百兆的內存至上G的內存,有的人拿它來應付很大內存就會出現問題,因為一旦老年代產生很多碎片,從新生代過來的對象就會出現找不到空間的情況,這叫做:PromotionFailed找不到空間。這時候它干了一件事情,把Serial Old 請出來,讓它用一個線程在這里進行標記壓縮。
floating garbage浮動垃圾:當出現Concurrent Mode Failure 和 PromotionFailed時,說明碎片較多,Old區內存分配不下,會調用Serial Old。並不是說使用了CMS之后這個問題沒辦法避免,可以降低觸發CMS的閾值。
解決方法降低CMS的閾值: -XX:CMSInitiatingOccupancyFraction 92% 可以降低這個值,讓CMS保持老年代有足夠的空間。
Remark階段的算法:
怎么才能進行並發標記呢 非常的復雜,CMS采用的是三色標記+Incremental Update 算法。
-
-
- 三色掃描算法:白灰黑
- 在並發標記時,引用可能發生變化,白色對象有可能會被錯誤回收
- 解決方法:SATB (snapshot at the beginning) 在起始的時候做一個快照
- Incremental Update : 當一個白色對象被一個黑色對象引用時,將黑色對象重新標記為灰色,讓垃圾回收器重新掃描;
-
常見的垃圾回收器就介紹這么多,下一篇會給大家介紹一下 PS+PO;如果寫的有誤的地方還請大佬指出;