垃圾收集器是jvm實現內存回收的具體實現。本次分享要介紹的7種垃圾收集器的做用區域及其之間的關係以下圖:
算法
注:多線程
算法 | 內存區域 | 執行方式 |
---|---|---|
複製算法 | 新生代 | 單線程、串行 |
先暫停所有用戶線程(Stop The World),而後開啓一條GC線程使用複製算法對垃圾進行回收。直到收集結束被暫停的線程才能繼續執行 併發
平時的開發與調試程序使用,以及桌面應用交互程序。jvm
算法 | 內存區域 | 執行方式 |
---|---|---|
標記/整理算法 | 老年代 | 單線程、串行 |
執行過程、特色、使用場景與Serial收集器相似性能
算法 | 內存區域 | 執行方式 |
---|---|---|
複製算法 | 新生代 | 多線程、並行 |
開啓多個GC線程使用複製算法並行進行垃圾回收 網站
在中到大型的堆上,且系統處理器至少多於一個的狀況。線程
算法 | 內存區域 | 執行方式 |
---|---|---|
複製算法 | 新生代 | 並行 |
ParNew收集器基本相似,只不過優先知足最大停頓時間的目標,次之是吞吐量,最後纔是新生代區域的最小值。設計
吞吐量=運行用戶代碼的時間/CPU總消耗時間調試
適用於與用戶交互的程序,良好的響應速度能提高用戶體驗,高吞吐量則能夠高效的利用cpu。主要適合在後臺運算而不須要太多交互的任務對象
算法 | 內存區域 | 執行方式 |
---|---|---|
標記/整理算法 | 老年代 | 並行 |
除了serial old之外惟一一個能夠與parallel scavenge搭配工做的年老代蒐集器
算法 | 內存區域 | 執行方式 |
---|---|---|
標記/清除算法 | 老年代 | 多線程、並行 |
1.初始標記階段,時間很短,只會標記直接與GC Root相連的對象 2.從新標記階段,時間比初始化標記稍長
在進行標記階段,標記的對象再也不從GC Root可達,所以在此次GC過程當中該對象內存空間不會被回收,所以形成了浮動垃圾。
這些浮動垃圾會佔用一些內存,但下次GC會被回收。
在併發標記階段,GC線程沒有標記(用戶線程以前沒在用),在標記過程當中,用戶線程又從新引用了該對象。若是該對象依然被回收,那麼程序就直接報錯了。
下面舉個例子說明,設計A是被GC Root相關聯的對象,假設如今正在搜索A相關聯的對象,這個時候A被標記爲灰色,搜索到A引用了B,這個時候B也會被標記爲灰色,以下圖
當A搜索完之後,A被標記爲綠色,這個時候直接與A相連的B和C已被標記爲灰色,但D沒有,由於D沒有直接與A相連,以下圖
而後繼續搜索B直接引用的對象,假設這個過程當中,C再也不引用D,以下圖
若是在搜索C相關的引用後,D依然處於不可達的狀態,假設這個時候已經標記完成的對象B引用了D,以下圖
若是D被回收,那麼在後面的程序確定會有問題
此時的解決辦法就是有一個叫作寫入屏障(注意在G1收集器中會比較)的東西。就是說,若是B已經被標記了(已是綠色的了),那麼用戶線程改動 B->D的時候,會把D變成灰色,這樣,之後就能夠搜索D了。
因爲其餘垃圾回收器都是 "stop the world",那麼內存不夠了就執行 GC。可是 CMS 垃圾回收器是能夠和用戶線程一塊兒併發的。假設在執行GC過程當中內存不夠了怎麼辦?這個時候就會有預備方案,Serial Old 垃圾回收器會替代 CMS,進行 "stop the world"垃圾收集。
使用-XX:CMSInitiatingOccupancyFraction的值來設定觸發GC的內存百分比
CMS是一款基於「標記-清除」算法實現的收集器,收集結束時會有大量的空間碎片產生。當沒法找到足夠大的連續空間來分配當前對象,不得不提早觸發一次full Gc。
默認是打開的,用戶在CMS收集器頂不要進行Full GC時開啓內存碎片的合併整理過程,內存整理的過程是沒法併發的,空間碎片的問題沒有了,但停頓的時間會變長
設置多少次不壓縮Full GC後,跟着來一次帶壓縮的碎片整理,默認爲0。
CMS收集器對CPU資源很是敏感.CMS默認啓動的回收線程數是(CPU數量+3)/4,在併發階段,它雖然不會致使用戶線程停頓,可是會佔用一部分線程而致使應用程序變慢,總吞吐量對下降。
重視服務的響應速度,但願系統的停頓時間最短,以帶來較好的用戶體驗,例如互聯網站或B/S系統的服務端上,
CMS垃圾收集器雖然減小了暫停應用程序的運行時間,可是它仍是存在着內存碎片問題。因而,爲了去除內存碎片問題,同時又保留CMS垃圾收集器低暫停時間的優勢,JAVA7發佈了一個新的垃圾收集器 - G1垃圾收集器。
Eden,Survivor和Tenured等內存區域再也不是連續的了,而是變成了一個個大小同樣的region - 每一個region從1M到32M不等。一個region有可能屬於Eden,Survivor或者Tenured內存區域。 在G1中,還有一種特殊的區域,叫Humongous區域。 若是一個對象佔用的空間超過了分區容量50%以上,G1收集器就認爲這是一個巨型對象。G1劃分了一個Humongous區,它用來專門存放巨型對象。若是一個H區裝不下一個巨型對象,那麼G1會尋找連續的H分區來存儲。爲了能找到連續的H區,有時候不得不啓動Full GC。
在G1垃圾收集器中CMS垃圾收集器差很少,回收Eden region和Survivor region上的非可達對象,同時升級存活的可達對象到對應的Survivor region或Tenured region上。
對於年老代上的垃圾收集,G1垃圾收集器也分爲4個階段,基本跟CMS垃圾收集器同樣,但略有不一樣: