JVM(HotSpot) 垃圾收集器

需要提前了解的知識:

  1. JVM內存模型
  2. JVM垃圾回收算法

HotSpot虛擬機所有的垃圾收集器如下圖:

HotSpot 所有垃圾收集器

上面有7種收集器,分為部分,上面為新生代收集器,下面是老年代收集器。如果兩個收集器之間存在連線,就說明它們可以搭配使用。

新生代的收集器使用復制算法,
老年代使用并發標記清除(CMS)或標記-整理算法。

Stop The World

Java中Stop-The-World機制簡稱STW,是在執行垃圾收集算法時,Java應用程序的其他所有線程都被掛起(除了垃圾收集幫助器之外)。Java中一種全局暫停現象,全局停頓,所有Java代碼停止,native代碼可以執行,但不能與JVM交互。

垃圾收集器

序號 收集器 收集范圍 算法 執行類型
1 Serial 新生代 復制 單線程
2 ParNew 新生代 復制 多線程并行
3 Parallel 新生代 復制 多線程并行
4 Serial Old 老年代 標記整理 單線程
5 CMS 老年代 標記清除 多線程并發
6 Parallel Old 老年代 標記整理 多線程
7 G1 全部 復制算法,標記-整理 多線程

解釋:
并行(Parallel):多條垃圾收集線程并行工作,而用戶線程仍處于等待狀態
并發(Concurrent):垃圾收集線程與用戶線程一段時間內同時工作(交替執行)

1、Serial(串行GC)收集器

Serial收集器是一個新生代收集器,單線程執行,使用復制算法。它在進行垃圾收集時,必 須暫停其他所有的工作線程(用戶線程)。是Jvm client模式下默認的新生代收集器。對于限定單個CPU的環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單 線程收集效率。


圖1

2、ParNew(并行GC)收集器

ParNew收集器其實就是serial收集器的多線程版本,除了使用多條線程進行垃圾收集之外,其余行為與Serial收集器一樣。


圖2

3、Parallel Scavenge(并行回收GC)收集器

Parallel Scavenge收集器也是一個新生代收集器,它也是使用復制算法的收集器,又是并行多線程收集器。parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量= 程序運行時間/(程序運行時間 + 垃圾收集時間),虛擬機總共運行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。

使用如下2個參數進行控制吞吐量

  1. -XX:MaxGCPauseMillis
    MaxGCPauseMillis參數允許的值是一個大于0的毫秒數,收集器將盡力保證內存回收花費的時間不超過設定值。
  2. -XX:GCTimeRatio
    GCTimeRatio參數的值應當是一個大于0小于100的整數,也就是垃圾收集時間占總時間的比率,相當于是吞吐量的倒數。如果把此參數設置為19,那允許的最大GC時間就占總時間的5%(即1 /(1+19)),默認值為99,就是允許最大1%(即1 /(1+99))的垃圾收集時間。

示意圖和ParNew類似(參見圖2)。

4、Serial Old(串行GC)收集器

Serial Old是Serial收集器的老年代版本,它同樣使用一個單線程執行收集,使用“標記-整理”算法。主要使用在Client模式下的虛擬機。如果在Server模式下,它主要還有兩大用途:一個是在JDK 1.5及之前的版本中與Parallel Scavenge收集器搭配使用,另外一個就是作為CMS收集器的后備預案。如果CMS收集器出現Concurrent Mode Failure,則Serial Old收集器將作為后備收集器。

詳見圖1 老年的收集

5、Parallel Old(并行GC)收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。


圖3

6、CMS(并發GC)收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。CMS收集器是基于“標記-清除”算法實現的,整個收集過程大致分為4個步驟:

  1. 初始標記(CMS initial mark)
  2. 并發標記(CMS concurrenr mark)
  3. 重新標記(CMS remark)
  4. 并發清除(CMS concurrent sweep)

其中初始標記、重新標記這兩個步驟任然需要停頓其他用戶線程。初始標記僅僅只是標記出GC ROOTS能直接關聯到的對象,速度很快,并發標記階段是進行GC ROOTS 根搜索算法階段,會判定對象是否存活。而重新標記階段則是為了修正并發標記期間,因用戶程序繼續運行而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比并發標記階段要短。

由于整個過程中耗時最長的并發標記和并發清除過程中,收集器線程都可以與用戶線程一起工作,所以整體來說,CMS收集器的內存回收過程是與用戶線程一起并發執行的。

CMS收集器的優點:并發收集、低停頓,但是CMS還遠遠達不到完美,器主要有三個顯著缺點:

  1. CMS收集器對CPU資源非常敏感。
    在并發階段,雖然不會導致用戶線程停頓,但是會占用CPU資源而導致引用程序變慢,總吞吐量下降。CMS默認啟動的回收線程數是:(CPU數量+3)/4。(建議CPU個數最少4個)。

  2. 無法處理浮動垃圾
    在做垃圾回收的過程中會產生新的垃圾(并行執行),所以需要預留一部分空間給用戶線程使用。
    可以使用-XX:CMSInitiatingOccupancyFraction(jdk1.6 默認為92%)參數來設置,預留多少空間開始做GC。如果在垃圾回收的過程中,剩余空間不足仍然滿足不了用戶線程生成對象所需要的空間,就會出現“Concurrent Mode Failure”失敗,這時候虛擬機將啟動后備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。

  3. CMS是基于“標記-清除”算法實現的收集器,使用“標記-清除”算法收集后,會產生大量碎片。
    空間碎片太多時,將會給對象分配帶來很多麻煩,比如說大對象,內存空間找不到連續的空間來分配不得不提前觸發一次Full GC。為了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關參數,用于在Full GC之后增加一個碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction參數設置執行多少次不壓縮的Full GC之后,跟著來一次碎片整理過程。


    圖4

7、G1收集器
G1(Garbage First)垃圾回收器是用在heap memory很大的情況下,把heap劃分為很多很多的region塊,然后并行的對其進行垃圾回收。
G1垃圾回收器在清除實例所占用的內存空間后,還會做內存壓縮。
G1垃圾回收器回收region的時候基本不會STW,而是基于 most garbage優先回收 的策略來對region進行垃圾回收的。

結果如下圖:


圖5

一個region有可能屬于Eden,Survivor或者Tenured內存區域。圖中的E表示該region屬于Eden內存區域,S表示屬于Survivor內存區域,T表示屬于Tenured內存區域。圖中空白的表示未使用的內存空間。G1垃圾收集器還增加了一種新的內存區域,叫做Humongous內存區域,如圖中的H塊。這種內存區域主要用于存儲大對象-即大小超過一個region大小的50%的對象。

年輕代垃圾收集

在G1垃圾收集器中,年輕代的垃圾回收過程使用復制算法。把Eden區和Survivor區的對象復制到新的Survivor區域。
如下圖:


圖6

老年代垃收集

對于年老代上的垃圾收集,G1垃圾收集器也分為4個階段,基本跟CMS垃圾收集器一樣,但略有不同:

Initial Mark階段 - 同CMS垃圾收集器的Initial Mark階段一樣,G1也需要暫停應用程序的執行,它會標記從根對象出發,在根對象的第一層孩子節點中標記所有可達的對象。但是G1的垃圾收集器的Initial Mark階段是跟minor gc一同發生的。也就是說,在G1中,你不用像在CMS那樣,單獨暫停應用程序的執行來運行Initial Mark階段,而是在G1觸發minor gc的時候一并將年老代上的Initial Mark給做了。

Concurrent Mark階段 - 在這個階段G1做的事情跟CMS一樣。但G1同時還多做了一件事情,就是如果在Concurrent Mark階段中,發現哪些Tenured region中對象的存活率很小或者基本沒有對象存活,那么G1就會在這個階段將其回收掉,而不用等到后面的clean up階段。這也是Garbage First名字的由來。同時,在該階段,G1會計算每個 region的對象存活率,方便后面的clean up階段使用 。

Remark階段 - 在這個階段G1做的事情跟CMS一樣, 但是采用的算法不同,G1采用一種叫做SATB(snapshot-at-the-begining)的算法能夠在Remark階段更快的標記可達對象。

Clean up/Copy階段 - 在G1中,沒有CMS中對應的Sweep階段。相反 它有一個Clean up/Copy階段,在這個階段中,G1會挑選出那些對象存活率低的region進行回收,這個階段也是和minor gc一同發生的,如下圖所示:

圖7

想了解更多精彩內容請關注我的公眾號

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容