深入理解Java虛擬機之經(jīng)典垃圾收集器
本文參考于《深入理解Java虛擬機》
1. 綜述
1. 總述:
如果說收集算法是內存回收的方法論,那垃圾收集器就是內存回收的實踐者?!禞ava虛擬機規(guī)范》中對垃圾收集器應該如何實現(xiàn)并沒有做出任何規(guī)定,因此不同的廠商、不同版本的虛擬機所包含的垃圾收集器都可能會有很大差別,不同的虛擬機一般也都會提供各種參數(shù)供用戶根據(jù)自己的應用特點和要求組合出各個內存分代所使用的收集器。
2. 圖示總述

上圖展示了七種作用于不同分代的收集器,如果
兩個收集器之間存在連線,就說明它們可以搭配使用,圖中收集器所處的區(qū)域,則表示它是屬于新生代收集器抑或是老年代收集器。
3. 應用中應如何做出選擇?
雖然我們會對各個收集器進行比較,但并非為了挑選一個最好的收集器出來,雖然垃圾收集器的技術在不斷進步,但直到現(xiàn)在還沒有最好的收集器出現(xiàn),更加不存在“萬能”的收集器,所以我們選擇的只是對具體應用最合適的收集器。這點不需要多加論述就能證明:如果有一種放之四海皆準、任何場景下都適用的完美收集器存在,HotSpot虛擬機完全沒必要實現(xiàn)那么多種不同的收集器了。
2. Serial收集器
1. 簡介
Serial收集器是最基礎、歷史最悠久的收集器,曾經(jīng)(在JDK 1.3.1之前)是HotSpot虛擬機新生代收集器的唯一選擇。大家只看名字就能夠猜到,這個收集器是一個單線程工作的收集器,但它的“單線程”的意義并不僅僅是說明它只會使用一個處理器或一條收集線程去完成垃圾收集工作,更重要的是強調在它進行垃圾收集時,必須暫停其他所有工作線程,直到它收集結束(“Stop The World”)。
2. 圖解工作過程

3.使用的垃圾收集算法
標記-復制算法
4. 優(yōu)點
簡單而高效(與其他收集器的單線程相比),對于內存資源受限的環(huán)境,它是所有收集器里額外內存消耗最小的;對于單核處理器或處理器核心數(shù)較少的環(huán)境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。
5. 缺點
在垃圾回收過程中會觸發(fā) “Stop The World” 而產(chǎn)生停頓,從而導致用戶體驗不好。
6. 主要應用場景
Serial收集器對于運行在客戶端模式下的虛擬機來說是一個很好的選擇。
3. ParNew收集器
1. 簡介
ParNew收集器實質上是Serial收集器的多線程并行版本(新生代收集器),除了同時使用多條線程進行垃圾收集之外,其余的行為包括Serial收集器可用的所有控制參數(shù)(例如:-XX:SurvivorRatio、-XX PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、對象分配規(guī)則、回收策略等都與Serial收集器完全一致,在實現(xiàn)上這兩種收集器也共用了相當多的代碼。
2. 圖解工作過程

3. 使用的垃圾收集算法
標記-復制算法
4. 補充概念
- 并行:并行描述的是
多條垃圾收集器線程之間的關系,說明同一時間有多條這樣的線程在協(xié)同工作,通常默認此時用戶線程是處于等待狀態(tài)。 - 并發(fā):并發(fā)描述的是
垃圾收集器線程與用戶線程之間的關系,說明同一時間垃圾收集器線程與用戶線程都在運行。由于用戶線程并未被凍結,所以程序仍然能響應服務請求,但由于垃圾收集器線程占用了一部分系統(tǒng)資源,此時應用程序的處理的吞吐量將受到一定影響。
5. 主要應用場景
它是許多運行在 Server 模式下的虛擬機的首要選擇,除了 Serial 收集器外,只有它能與 CMS 收集器(真正意義上的并發(fā)收集器,后面會介紹到)配合工作。
4. Parallel Scavenge收集器
1. 簡介
Parallel Scavenge收集器也是一款新生代收集器,它同樣是基于標記-復制算法實現(xiàn)的收集器,也是能夠并行收集的多線程收集器。Parallel Scavenge的諸多特性從表面上看和ParNew非常相似。Parallel Scavenge收集器的特點是它的關注點與其他收集器不同,CMS等收集器的關注點是盡可能地縮短垃圾收集時用戶線程的停頓時間,而Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。
2. 補充概念
吞吐量就是處理器用于運行用戶代碼的時間與處理器總消耗時間的比值。

如果虛擬機完成某個任務,用戶代碼加上垃圾收集總共耗費了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
停頓時間越短就越適合需要與用戶交互或需要保證服務響應質量的程序,良好的響應速度能提升用戶體驗;而高吞吐量則可以最高效率地利用處理器資源,盡快完成程序的運算任務,主要適合在后臺運算而不需要太多交互的分析任務。
3. 圖解工作過程

4. 使用的垃圾收集算法
標記-復制算法
5. 相關的參數(shù)
Parallel Scavenge收集器提供了兩個參數(shù)用于精確控制吞吐量,分別是控制最大垃圾收集停頓時間的 -XX:MaxGCPauseMillis 參數(shù)以及直接設置吞吐量大小的 -XX:GCTimeRatio 參數(shù)。
5. Serial Old收集器
1. 簡介
Serial Old是Serial收集器的老年代版本,它同樣是一個單線程收集器,使用標記-整理算法。
2. 圖解工作過程

3. 使用的垃圾收集算法
標記-整理算法
4. 主要的應用場景
供客戶端模式下的HotSpot虛擬機使用。- 在服務端模式下,一種在JDK 5以及之前的版本中
與Parallel Scavenge收集器搭配使用;另外一種就是作為CMS收集器發(fā)生失敗時的后備預案。
6. Parallel Old收集器
1. 簡介
Parallel Old是Parallel Scavenge收集器的老年代版本,支持多線程并發(fā)收集,基于標記-整理算法實現(xiàn)。
2. 圖解工作過程

3. 使用的垃圾收集算法
標記-整理算法
4. 主要的應用場景
注重吞吐量或者處理器資源較為稀缺的場合,都可以優(yōu)先考慮Parallel Scavenge 加 Parallel Old收集器這個組合。
7. CMS收集器
1. 簡介
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。CMS收集器是基于標記-清除算法實現(xiàn)的。它非常適合在注重用戶體驗的應用上使用。
2. 工作過程
- 初始標記:
標記一下GC Roots能直接關聯(lián)到的對象,速度很快 - 并發(fā)標記:從GC Roots的直接關聯(lián)對象開始遍歷整個對象圖的過程,這個過程耗時較長但是
不需要停頓用戶線程,用戶線程可以與垃圾收集線程一起并發(fā)運行。 - 重新標記:為了
修正并發(fā)標記期間因用戶程序繼續(xù)運作而導致標記產(chǎn)生變動的那一部分對象的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長一些,但也遠比并發(fā)標記階段的時間短。 - 并發(fā)清除:
清理刪除掉標記階段判斷的已經(jīng)死亡的對象,由于不需要移動存活對象,所以這個階段也是可以與用戶線程同時并發(fā)的。
3. 圖解工作過程

4. 使用的垃圾收集算法
標記-清除算法。
5. 優(yōu)點
回收停頓時間短,給用戶帶來良好的交互體驗。并發(fā)收集
6. 缺點
對處理器資源非常敏感無法處理“浮動垃圾”- 因為CMS收集器是一款基于標記-清除算法的垃圾收集器,
其收集結束時會有大量空間碎片產(chǎn)生。
7. 主要的應用場景
它非常適合在注重用戶體驗和要求停頓時間短的應用上使用。
8. Garbage First收集器
1. 簡介
G1 (Garbage-First) 是一款面向服務器的垃圾收集器,主要針對配備多顆處理器及大容量內存的機器。以極高概率滿足 GC 停頓時間要求的同時,還具備高吞吐量性能特征。G1在后臺維護一個優(yōu)先級列表,每次根據(jù)用戶設定允許的收集停頓時間,優(yōu)先處理回收價值收益最大的那些Region。這種使用 Region劃分內存空間以及有優(yōu)先級的區(qū)域回收方式,保證了 G1 收集器在有限時間內可以盡可能高的收集效率(把內存化整為零)。
2. 工作過程
- 初始標記:僅僅
只是標記一下GC Roots能直接關聯(lián)到的對象,并且修改TAMS指針的值,讓下一階段用戶線程并發(fā)運行時,能正確地在可用的Region中分配新對象。這個階段需要停頓線程,但耗時很短,而且是借用進行Minor GC的時候同步完成的,所以G1收集器在這個階段實際并沒有額外的停頓。 - 并發(fā)標記:從GC Root開始對堆中對象進行可達性分析,遞歸掃描整個堆里的對象圖,
找出要回收的對象,這階段耗時較長,但可與用戶程序并發(fā)執(zhí)行。當對象圖掃描完成以后,還要重新處理SATB記錄下的在并發(fā)時有引用變動的對象。最終標記:對用戶線程做另一個短暫的暫停,用于處理并發(fā)階段結束后仍遺留下來的最后那少量的SATB記錄。 - 篩選回收:負責更新Region的統(tǒng)計數(shù)據(jù),
對各個Region的回收價值和成本進行排序,根據(jù)用戶所期望的停頓時間來制定回收計劃,可以自由選擇任意多個Region構成回收集,然后把決定回收的那一部分Region的存活對象復制到空的Region中,再清理掉整個舊Region的全部空間。這里的操作涉及存活對象的移動,是必須暫停用戶線程,由多條收集器線程并行完成的。
從上述階段的描述可以看出,G1收集器除了并發(fā)標記外,其余階段也是要完全暫停用戶線程的,換言之,它
并非純粹地追求低延遲,官方給它設定的目標是在延遲可控的情況下獲得盡可能高的吞吐量,所以才能擔當起“全功能收集器”的重任與期望。
3. 圖解工作過程

4. 特點
- 并行與并發(fā):
- 分代收集
- 空間整合
- 可預測的停頓
5. 使用此收集器下的堆內存說明

G1不再堅持固定大小以及固定數(shù)量的分代區(qū)域劃分,而是把連續(xù)的Java堆劃分為多個大小相等的獨立區(qū)域(Region),每一個Region都可以根據(jù)需要,扮演新生代的Eden空間、Survivor空間,或者老年代空間。收集器能夠對扮演不同角色的Region采用不同的策略去處理,這樣無論是新創(chuàng)建的對象還是已經(jīng)存活了一段時間、熬過多次收集的舊對象都能獲取很好的收集效果。Region中還有一類特殊的Humongous區(qū)域(H),專門用來存儲大對象。G1認為只要大小超過了一個Region容量一半的對象即可判定為大對象。每個Region的大小可以通過參數(shù)-XX:G1HeapRegionSize設定,取值范圍為1MB~32MB,且應為2的N次冪。而對于那些超過了整個Region容量的超級大對象,將會被存放在N個連續(xù)的Humongous Region之中,G1的大多數(shù)行為都把Humongous Region作為老年代的一部分來進行看待,如上圖所示。雖然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它們都是一系列區(qū)域(不需要連續(xù))的動態(tài)集合。
6. 主要的應用場景
主要使用于服務端模式下的垃圾回收。
到此這篇關于深入理解Java虛擬機之經(jīng)典垃圾收集器的文章就介紹到這了,更多相關java垃圾收集器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java布爾值Boolean和boolean之間轉換實例用法
在本篇文章里小編給大家整理的是一篇關于Java布爾值Boolean和boolean之間轉換實例用法內容,有需要的朋友們跟著學習參考下。2021-06-06
SpringMVC中controller接收json數(shù)據(jù)的方法
這篇文章主要為大家詳細介紹了SpringMVC中controller接收json數(shù)據(jù)的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09

