JVM 垃圾回收器分類
1. 前言
本節主要講解 7 種垃圾回收器,其中有 3 種垃圾回收器是作用于年輕代垃圾回收的收集器;另外 3 種圾回收器是作用于老年代垃圾回收的收集器;剩余的 1 種垃圾回收器能夠同時作用于年輕代和老年代。
7 種垃圾回收器以及其作用的內存區域如下圖所示:
通篇皆為重點知識,請認真學習并理解每種垃圾回收器的特點。
2. Serial收集器
基本概念:Serial收集器是最基本、發展歷史最久的收集器,這個收集器是采用復制算法的單線程的收集器。
Tips:從概念上來看,我們需要注意Serial收集器的兩個特點:一個是采用復制算法,另外一個是單線程收集。
單線程的收集器:單線程一方面意味著他只會使用一個 CPU 或者一條線程去完成垃圾收集工作,另一方面也意味著他進行垃圾收集時必須暫停其他線程的所有工作,直到它收集結束為止。
不過實際上到目前為止,Serial收集器依然是虛擬機運行在 Client 模式下的默認新生代收集器,因為它簡單而高效。Serial 收集器運行過程如下圖所示:
3. Parnew收集器
基本概念:Parnew 收集器其實就是Serial收集器的多線程版本,除了使用多線程進行垃圾收集外,其余行為和 Serial 收集器完全一樣,但是他卻是 Server 模式下的虛擬機首選的新生代收集器。
Tips:從概念上來看,我們需要注意Parnew收集器的兩個特點:一個是采用復制算法,另外一個是多線程收集。
特點:
- 除了 Serial 收集器外,目前只有它能與 CMS 收集器配合工作。CMS 收集器第一次實現了讓垃圾收集器與用戶線程基本上同時工作;
- Parnew 收集器默認開啟的收集線程數與 CPU 數量相同,在 CPU 數量非常多的情況下,可以使用
-XX:ParallelGCThreads
參數來限制垃圾收集的線程數。
Parnew 收集器運行過程如圖所示:
4. Parallel Scavenge收集器
基本概念:Parallel Scavenge 收集器也是一個新生代收集器,也采用了復制算法,也是并行的多線程收集器。Parallel Scavenge 收集器的目標是達到一個可控制的吞吐量。Parallel Scavenge 收集器是虛擬機運行在 Server 模式下的默認垃圾收集器。被稱為“吞吐量優先收集器”。
Tips:從概念上來看,我們需要注意Parallel Scavenge收集器的三個個特點:一個是采用復制算法,一個是多線程收集,一個是達到控制吞吐量的目標。
Parallel Scavenge 收集器運行過程同 Parnew 收集器一樣:
控制吞吐量:CMS 等收集器的關注點是盡可能縮短垃圾收集時用戶線程的停頓時間,而 Parallel Scavenge 收集器的目標則是達到一個可控制的吞吐量。所謂吞吐量就是 CPU 用于運行用戶代碼時間與 CPU 總消耗時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
。
空間吞吐量參數介紹:虛擬機提供了-XX:MaxGCPauseMills
和 -XX:GCTimeRatio
兩個參數來精確控制最大垃圾收集停頓時間和吞吐量大小。不過不要以為前者越小越好,GC 停頓時間的縮短是以犧牲吞吐量和新生代空間換取的。由于與吞吐量關系密切,Parallel Scavenge 收集器也被稱為“吞吐量優先收集器”。
Parallel Scavenge 收集器有一個參數 -XX:UseAdaptiveSizePolicy 參數,這是一個開關參數,這個參數打開之后,就不需要手動指定新生代大小、Eden 區和 Survivor 參數等細節參數了,虛擬機會根據當前系統的運行情況以及性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量。
如果對于垃圾收集器運作原理不太了解,以至于在優化比較困難的時候,可以使用 Parallel Scavenge收集器配合自適應調節策略,把內存管理的調優任務交給虛擬機去完成。
5. Serial Old收集器
基本概念: Serial Old 收集器同樣是一個單線程收集器,作用于老年代,使用“標記-整理算法”,這個收集器的主要意義也是在于給 Client 模式下的虛擬機使用。
Serial Old 收集器運行過程如圖所示:
6. Parallel Old收集器
基本概念: Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,使用多線程和“標記-整理算法”進行垃圾回收。
這個收集器在 JDK 1.6 之后的出現,“吞吐量優先收集器”終于有了比較名副其實的應用組合,在注重吞吐量以及 CPU 資源敏感的場合,都可以優先考慮 Parallel Scavenge收集器+Parallel Old收集器
的組合。
Parallel Scavenge 收集器+Parallel Old 收集器
的組合運行過程如下圖所示:
7. CMS收集器
基本概念:CMS(Conrrurent Mark Sweep,連續標記掃描)收集器是以獲取最短回收停頓時間為目標的收集器。使用標記-清除算法。
收集步驟:收集過程分為如下四步:
- 初始標記:標記 GCRoots 能直接關聯到的對象,時間很短;
- 并發標記:進行 GCRoots Tracing(可達性分析)過程,時間很長;
- 重新標記:修正并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,時間較長;
- 并發清除:回收內存空間,時間很長。其中,并發標記與并發清除兩個階段耗時最長,但是可以與用戶線程并發執行。
CMS 收集器運行過程如下圖所示:
8. G1收集器
基本概念:G1 是目前技術發展的最前沿成果之一,HotSpot開發團隊賦予它的使命是未來可以替換掉 JDK1.5 中發布的 CMS 收集器。
與其他GC收集器相比,G1收集器具有以下特點:
- 并發和并行:使用多個 CPU 來縮短 Stop The World 停頓時間,與用戶線程并發執行;
- 分代收集:獨立管理整個堆,但是能夠采用不同的方式去處理新創建對象和已經存活了一段時間、熬過多次 GC 的舊對象,以獲取更好的收集效果;
- 空間整合:基于標記-整理算法,無內存碎片產生;
- 可預測的停頓:能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為 M 毫秒的時間片段內,消耗在垃圾收集器上的時間不得超過N毫秒。
在G1之前的垃圾收集器,收集的范圍都是整個新生代或者老年代,而 G1 不再是這樣。使用 G1 收集器時,Java 堆的內存布局與其他收集器有很大差別,它將整個Java堆劃分為多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分(可以不連續)Region 的集合。
9. 小結
本節主要講解了 7 種垃圾收集器:Serial 收集器,Parnew 收集器,Parallel Scavenge 收集器,Serial Old 收集器,Parallel Old 收集器,CMS 收集器和G1 收集器。
其中專門針對年輕代的收集器有 Serial 收集器,Parnew 收集器和 Parallel Scavenge 收集器;專門作用于老年代的收集器有Serial Old 收集器,Parallel Old 收集器和 CMS 收集器;而 G1 收集器即能夠作用于年輕代,也能夠作用于老年代。
學習者需要對這 7 種垃圾回收器進行理解,并掌握其作用的內存區域。