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