JVM垃圾收集器整理

概述

垃圾收集器是jvm實現內存回收的具體實現。本次分享要介紹的7種垃圾收集器的做用區域及其之間的關係以下圖:
image算法

 注:多線程

  • 若是2個垃圾收集器之間有連線,表示能夠搭配使用
  • 垃圾收集器並無最好的,只有針對不一樣應用場景最合適的

(1)Serial收集器

算法 內存區域 執行方式
複製算法 新生代 單線程、串行

過程

先暫停所有用戶線程(Stop The World),而後開啓一條GC線程使用複製算法對垃圾進行回收。直到收集結束被暫停的線程才能繼續執行 image併發

特色

  • 簡單而高線,對單CPU環境沒有線程交互的開銷。
  • 因爲單線程運行,且整個GC階段都要暫停用戶線程,所以會形成應用程序停頓。
  • client模式下的默認垃圾收集器

使用場景

平時的開發與調試程序使用,以及桌面應用交互程序。jvm

(2)Serial Old收集器

算法 內存區域 執行方式
標記/整理算法 老年代 單線程、串行

執行過程、特色、使用場景與Serial收集器相似性能

(3)ParNew收集器

算法 內存區域 執行方式
複製算法 新生代 多線程、並行

過程

開啓多個GC線程使用複製算法並行進行垃圾回收 image網站

特色

  • 使用多個線程去並行執行垃圾回收,在發揮多處理器的優點
  • 在單處理器上的性能會低於Serial收集器(線程交互開銷)
  • 執行垃圾回收也須要暫停其餘用戶線程

使用場景

在中到大型的堆上,且系統處理器至少多於一個的狀況。線程

(4)Parallel Scavenge收集器

算法 內存區域 執行方式
複製算法 新生代 並行

過程

ParNew收集器基本相似,只不過優先知足最大停頓時間的目標,次之是吞吐量,最後纔是新生代區域的最小值。設計

吞吐量=運行用戶代碼的時間/CPU總消耗時間調試

特色

  • 更精確的控制GC停頓時間以及吞吐量
  • 控制最大的停頓時間(使用-XX:MaxGCPauseMillis=),以及控制吞吐量(使用-XX:GCTimeRatio=)

使用場景

適用於與用戶交互的程序,良好的響應速度能提高用戶體驗,高吞吐量則能夠高效的利用cpu。主要適合在後臺運算而不須要太多交互的任務對象

Parallel Old收集器

算法 內存區域 執行方式
標記/整理算法 老年代 並行

特色

除了serial old之外惟一一個能夠與parallel scavenge搭配工做的年老代蒐集器

CMS收集器

算法 內存區域 執行方式
標記/清除算法 老年代 多線程、並行

過程

  • 初始標記(CMS initial mark):須要用戶線程停頓。標記一下GC Roots能直接關聯到的對象
  • 併發標記(CMS concurrent mark):以初始標記的對象爲root進行併發標記。
  • 從新標記(CMS remark):須要用戶線程停頓,是爲了修正併發標記期間因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄。
  • 併發清除(CMS concurrent sweap):清除標記的對象 image

特色

1.會有2次Stop The World

1.初始標記階段,時間很短,只會標記直接與GC Root相連的對象 2.從新標記階段,時間比初始化標記稍長

2.浮動垃圾

產生緣由

在進行標記階段,標記的對象再也不從GC Root可達,所以在此次GC過程當中該對象內存空間不會被回收,所以形成了浮動垃圾。

影響

這些浮動垃圾會佔用一些內存,但下次GC會被回收。

3.三色標記法

產生緣由

併發標記階段,GC線程沒有標記(用戶線程以前沒在用),在標記過程當中,用戶線程又從新引用了該對象。若是該對象依然被回收,那麼程序就直接報錯了。

標記過程

下面舉個例子說明,設計A是被GC Root相關聯的對象,假設如今正在搜索A相關聯的對象,這個時候A被標記爲灰色,搜索到A引用了B,這個時候B也會被標記爲灰色,以下圖

 image
當A搜索完之後,A被標記爲綠色,這個時候直接與A相連的B和C已被標記爲灰色,但D沒有,由於D沒有直接與A相連,以下圖
image
而後繼續搜索B直接引用的對象,假設這個過程當中,C再也不引用D,以下圖
image
若是在搜索C相關的引用後,D依然處於不可達的狀態,假設這個時候已經標記完成的對象B引用了D,以下圖
image 若是D被回收,那麼在後面的程序確定會有問題

解決辦法

此時的解決辦法就是有一個叫作寫入屏障(注意在G1收集器中會比較)的東西。就是說,若是B已經被標記了(已是綠色的了),那麼用戶線程改動 B->D的時候,會把D變成灰色,這樣,之後就能夠搜索D了。 image

4.Concurrent Mode Failure

因爲其餘垃圾回收器都是 "stop the world",那麼內存不夠了就執行 GC。可是 CMS 垃圾回收器是能夠和用戶線程一塊兒併發的。假設在執行GC過程當中內存不夠了怎麼辦?這個時候就會有預備方案,Serial Old 垃圾回收器會替代 CMS,進行 "stop the world"垃圾收集。

使用-XX:CMSInitiatingOccupancyFraction的值來設定觸發GC的內存百分比

5.空間碎片

CMS是一款基於「標記-清除」算法實現的收集器,收集結束時會有大量的空間碎片產生。當沒法找到足夠大的連續空間來分配當前對象,不得不提早觸發一次full Gc。

-XX:+UseCMSCompactAtFullCollection

默認是打開的,用戶在CMS收集器頂不要進行Full GC時開啓內存碎片的合併整理過程,內存整理的過程是沒法併發的,空間碎片的問題沒有了,但停頓的時間會變長

-XX:CMSFullGCBeforeCompaction

設置多少次不壓縮Full GC後,跟着來一次帶壓縮的碎片整理,默認爲0。

6.吞吐量影響

CMS收集器對CPU資源很是敏感.CMS默認啓動的回收線程數是(CPU數量+3)/4,在併發階段,它雖然不會致使用戶線程停頓,可是會佔用一部分線程而致使應用程序變慢,總吞吐量對下降。

使用場景

重視服務的響應速度,但願系統的停頓時間最短,以帶來較好的用戶體驗,例如互聯網站或B/S系統的服務端上,

G1收集器

CMS垃圾收集器雖然減小了暫停應用程序的運行時間,可是它仍是存在着內存碎片問題。因而,爲了去除內存碎片問題,同時又保留CMS垃圾收集器低暫停時間的優勢,JAVA7發佈了一個新的垃圾收集器 - G1垃圾收集器。

內存組織方式變動

Eden,Survivor和Tenured等內存區域再也不是連續的了,而是變成了一個個大小同樣的region - 每一個region從1M到32M不等。一個region有可能屬於Eden,Survivor或者Tenured內存區域。 image 在G1中,還有一種特殊的區域,叫Humongous區域。 若是一個對象佔用的空間超過了分區容量50%以上,G1收集器就認爲這是一個巨型對象。G1劃分了一個Humongous區,它用來專門存放巨型對象。若是一個H區裝不下一個巨型對象,那麼G1會尋找連續的H分區來存儲。爲了能找到連續的H區,有時候不得不啓動Full GC。

新生代收集

在G1垃圾收集器中CMS垃圾收集器差很少,回收Eden region和Survivor region上的非可達對象,同時升級存活的可達對象到對應的Survivor region或Tenured region上。 image

老年代收集

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

    • 初始化標記:過程和CMS基本相似,不一樣的是該階段在觸發YGC的時候執行(有什麼好處?)
    • 併發標記階段:和CMS基本相似,不一樣的是在該階段,G1會計算每一個 region的對象存活率,方便後面的clean up階段使用。
    • 從新標記:和CMS基本相似,但採起算法不同,G1採用一種叫作SATB(snapshot-at-the-begining)的算法可以在從新階段更快的標記可達對象。(CMS是使用寫入屏障)
    • Clean up/Copy階段 - 在G1中,沒有CMS中對應的併發清楚階段。相反 它有一個Clean up/Copy階段,在這個階段中,G1會挑選出那些對象存活率低的region進行回收,這個階段也是和minor gc一同發生的,以下圖所示image
相關文章
相關標籤/搜索