深入理解java虛擬機(4)HotSpot垃圾收集器與內存分配策略

HotSpot 虛擬機提供了多種垃圾收集器,每種收集器都有各自的特點,雖然我們要對各個收集器進行比較,但並非爲了挑選出一個最好的收集器。我們選擇的只是對具體應用最合適的收集器。

新生代垃圾收集器

Serial 垃圾收集器(單線程)

只開啓一條 GC 線程進行垃圾回收,並且在垃圾收集過程中停止一切用戶線程(Stop The World)。

一般客戶端應用所需內存較小,不會創建太多對象,而且堆內存不大,因此垃圾收集器回收時間短,即使在這段時間停止一切用戶線程,也不會感覺明顯卡頓。因此 Serial 垃圾收集器適合客戶端使用。

由於 Serial 收集器只使用一條 GC 線程,避免了線程切換的開銷,從而簡單高效。

ParNew 垃圾收集器(多線程)

ParNew 是 Serial 的多線程版本。由多條 GC 線程並行地進行垃圾清理。但清理過程依然需要 Stop The World。

ParNew 追求“低停頓時間”,與 Serial 唯一區別就是使用了多線程進行垃圾收集,在多 CPU 環境下性能比 Serial 會有一定程度的提升;但線程切換需要額外的開銷,因此在單 CPU 環境中表現不如 Serial。

Parallel Scavenge 垃圾收集器(多線程)

Parallel Scavenge 和 ParNew 一樣,都是多線程、新生代垃圾收集器。但是兩者有巨大的不同點:

  1. Parallel Scavenge:追求 CPU 吞吐量,能夠在較短時間內完成指定任務,因此適合沒有交互的後臺計算。

  2. ParNew:追求降低用戶停頓時間,適合交互式應用。

吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)

追求高吞吐量,可以通過減少 GC 執行實際工作的時間,然而,僅僅偶爾運行 GC 意味着每當 GC 運行時將有許多工作要做,因爲在此期間積累在堆中的對象數量很高。單個 GC 需要花更多的時間來完成,從而導致更高的暫停時間。而考慮到低暫停時間,最好頻繁運行 GC 以便更快速完成,反過來又導致吞吐量下降。

  1. 通過參數 -XX:GCTimeRadio 設置垃圾回收時間佔總 CPU 時間的百分比。

  2. 通過參數 -XX:MaxGCPauseMillis 設置垃圾處理過程最久停頓時間。

  3. 通過命令 -XX:+UseAdaptiveSizePolicy 開啓自適應策略。我們只要設置好堆的大小和 MaxGCPauseMillis 或 GCTimeRadio,收集器會自動調整新生代的大小、Eden 和 Survivor 的比例、對象進入老年代的年齡,以最大程度上接近我們設置的 MaxGCPauseMillis 或 GCTimeRadio。

老年代垃圾收集器

Serial Old 垃圾收集器(單線程)

Serial Old 收集器是 Serial 的老年代版本,都是單線程收集器,只啓用一條 GC 線程,都適合客戶端應用。它們唯一的區別就是:Serial Old 工作在老年代,使用“標記-整理”算法;Serial 工作在新生代,使用“複製”算法。

Parallel Old 垃圾收集器(多線程)

Parallel Old 收集器是 Parallel Scavenge 的老年代版本,追求 CPU 吞吐量。

CMS 垃圾收集器

CMS(Concurrent Mark Sweep,併發標記清除)收集器是以獲取最短回收停頓時間爲目標的收集器(追求低停頓),它在垃圾收集時使得用戶線程和 GC 線程併發執行,因此在垃圾收集過程中用戶也不會感到明顯的卡頓。

  • 初始標記:Stop The World,僅使用一條初始標記線程對所有與 GC Roots 直接關聯的對象進行標記。

  • 併發標記:使用多條標記線程,與用戶線程併發執行。此過程進行可達性分析,標記出所有廢棄對象。速度很慢。

  • 重新標記:Stop The World,使用多條標記線程併發執行,將剛纔併發標記過程中新出現的廢棄對象標記出來。

  • 併發清除:只使用一條 GC 線程,與用戶線程併發執行,清除剛纔標記的對象。這個過程非常耗時。

併發標記與併發清除過程耗時最長,且可以與用戶線程一起工作,因此,總體上說,CMS收集器的內存回收過程是與用戶線程一起併發執行的。

CMS的缺點:

  1. 吞吐量低

  2. 無法處理浮動垃圾,導致頻繁Full GC

  3. 使用“標記 - 清除”算法產生碎片空間

對於產生碎片空間的問題,可以通過開啓-XX:+ UseCMSCompactAtFullCollection,在每次完全GC完成後都會進行一次內存壓縮整理,將零散在各處的對象整理到一塊。設置參數-XX:CMSFullGCsBeforeCompaction告訴CMS,經過了N次Full GC之後再進行一次內存整理。

G1通用垃圾收集器

G1是一款面向服務端應用的垃圾收集器,它沒有新生代和老年代的概念,而是將堆劃分爲一塊塊獨立的Region。當要進行垃圾收集時,首先估計每個地區中垃圾的數量,每次都從垃圾回收價值最大的地區開始回收,因此可以獲得最大的回收效率。

從整體上看,G1是基於“標記 - 整理”算法實現的收集器,從局部(兩個區域之間)上看是基於“複製”算法實現的,這意味着運行期間不會產生內存空間碎片。

這裏拋個問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章