深入理解Java虛擬機(jī)之經(jīng)典垃圾收集器
本文參考于《深入理解Java虛擬機(jī)》
1. 綜述
1. 總述:
如果說收集算法是內(nèi)存回收的方法論,那垃圾收集器就是內(nèi)存回收的實(shí)踐者?!禞ava虛擬機(jī)規(guī)范》中對(duì)垃圾收集器應(yīng)該如何實(shí)現(xiàn)并沒有做出任何規(guī)定,因此不同的廠商、不同版本的虛擬機(jī)所包含的垃圾收集器都可能會(huì)有很大差別,不同的虛擬機(jī)一般也都會(huì)提供各種參數(shù)供用戶根據(jù)自己的應(yīng)用特點(diǎn)和要求組合出各個(gè)內(nèi)存分代所使用的收集器。
2. 圖示總述
上圖展示了七種作用于不同分代的收集器,如果
兩個(gè)收集器之間存在連線
,就說明它們可以搭配使用
,圖中收集器所處的區(qū)域
,則表示它是屬于新生代收集器抑或是老年代收集器
。
3. 應(yīng)用中應(yīng)如何做出選擇?
雖然我們會(huì)對(duì)各個(gè)收集器進(jìn)行比較,但并非為了挑選一個(gè)最好的收集器出來
,雖然垃圾收集器的技術(shù)在不斷進(jìn)步,但直到現(xiàn)在還沒有最好的收集器出現(xiàn),更加不存在“萬能”的收集器,所以我們選擇的只是對(duì)具體應(yīng)用最合適的收集器
。這點(diǎn)不需要多加論述就能證明:如果有一種放之四海皆準(zhǔn)、任何場(chǎng)景下都適用的完美收集器存在,HotSpot虛擬機(jī)完全沒必要實(shí)現(xiàn)那么多種不同的收集器了。
2. Serial收集器
1. 簡(jiǎn)介
Serial收集器是最基礎(chǔ)、歷史最悠久的收集器,曾經(jīng)(在JDK 1.3.1之前)是HotSpot虛擬機(jī)新生代收集器
的唯一選擇。大家只看名字就能夠猜到,這個(gè)收集器是一個(gè)單線程工作的收集器
,但它的“單線程”的意義并不僅僅是說明它只會(huì)使用一個(gè)處理器或一條收集線程去完成垃圾收集工作
,更重要的是強(qiáng)調(diào)在它進(jìn)行垃圾收集時(shí),必須暫停其他所有工作線程
,直到它收集結(jié)束(“Stop The World”)。
2. 圖解工作過程
3.使用的垃圾收集算法
標(biāo)記-復(fù)制算法
4. 優(yōu)點(diǎn)
簡(jiǎn)單而高效(與其他收集器的單線程相比),對(duì)于內(nèi)存資源受限的環(huán)境
,它是所有收集器里額外內(nèi)存消耗最小
的;對(duì)于單核處理器或處理器核心數(shù)較少的環(huán)境
來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率
。
5. 缺點(diǎn)
在垃圾回收過程中會(huì)觸發(fā) “Stop The World” 而產(chǎn)生停頓
,從而導(dǎo)致用戶體驗(yàn)不好。
6. 主要應(yīng)用場(chǎng)景
Serial收集器對(duì)于運(yùn)行在客戶端模式下的虛擬機(jī)
來說是一個(gè)很好的選擇。
3. ParNew收集器
1. 簡(jiǎn)介
ParNew收集器實(shí)質(zhì)上是Serial收集器的多線程并行版本
(新生代收集器),除了同時(shí)使用多條線程進(jìn)行垃圾收集之外,其余的行為包括Serial收集器可用的所有控制參數(shù)
(例如:-XX:SurvivorRatio、-XX PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法
、Stop The World
、對(duì)象分配規(guī)則
、回收策略
等都與Serial收集器完全一致,在實(shí)現(xiàn)上這兩種收集器也共用了相當(dāng)多的代碼。
2. 圖解工作過程
3. 使用的垃圾收集算法
標(biāo)記-復(fù)制算法
4. 補(bǔ)充概念
- 并行:并行描述的是
多條垃圾收集器線程之間的關(guān)系
,說明同一時(shí)間
有多條這樣的線程在協(xié)同工作,通常默認(rèn)此時(shí)用戶線程是處于等待狀態(tài)。 - 并發(fā):并發(fā)描述的是
垃圾收集器線程與用戶線程之間的關(guān)系
,說明同一時(shí)間
垃圾收集器線程與用戶線程都在運(yùn)行。由于用戶線程并未被凍結(jié),所以程序仍然能響應(yīng)服務(wù)請(qǐng)求,但由于垃圾收集器線程占用了一部分系統(tǒng)資源,此時(shí)應(yīng)用程序的處理的吞吐量將受到一定影響。
5. 主要應(yīng)用場(chǎng)景
它是許多運(yùn)行在 Server 模式下的虛擬機(jī)的首要選擇,除了 Serial 收集器外
,只有它能與 CMS 收集器
(真正意義上的并發(fā)收集器,后面會(huì)介紹到)配合工作。
4. Parallel Scavenge收集器
1. 簡(jiǎn)介
Parallel Scavenge收集器也是一款新生代收集器
,它同樣是基于標(biāo)記-復(fù)制算法實(shí)現(xiàn)的收集器,也是能夠并行收集的多線程收集器
。Parallel Scavenge的諸多特性從表面上看和ParNew非常相似。Parallel Scavenge收集器的特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同,CMS等收集器的關(guān)注點(diǎn)是盡可能地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間
,而Parallel Scavenge收集器的目標(biāo)則是達(dá)到一個(gè)可控制的吞吐量
。
2. 補(bǔ)充概念
吞吐量就是處理器用于運(yùn)行用戶代碼的時(shí)間與處理器總消耗時(shí)間的比值
。
如果虛擬機(jī)完成某個(gè)任務(wù),用戶代碼加上垃圾收集總共耗費(fèi)了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
停頓時(shí)間越短
就越適合需要與用戶交互或需要保證服務(wù)響應(yīng)質(zhì)量的程序
,良好的響應(yīng)速度能提升用戶體驗(yàn);而高吞吐量則可以最高效率地利用處理器資源
,盡快完成程序的運(yùn)算任務(wù),主要適合在后臺(tái)運(yùn)算而不需要太多交互的分析任務(wù)
。
3. 圖解工作過程
4. 使用的垃圾收集算法
標(biāo)記-復(fù)制算法
5. 相關(guān)的參數(shù)
Parallel Scavenge收集器提供了兩個(gè)參數(shù)用于精確控制吞吐量
,分別是控制最大垃圾收集停頓時(shí)間
的 -XX:MaxGCPauseMillis 參數(shù)以及直接設(shè)置吞吐量大小
的 -XX:GCTimeRatio 參數(shù)。
5. Serial Old收集器
1. 簡(jiǎn)介
Serial Old是Serial收集器的老年代版本
,它同樣是一個(gè)單線程收集器
,使用標(biāo)記-整理算法。
2. 圖解工作過程
3. 使用的垃圾收集算法
標(biāo)記-整理算法
4. 主要的應(yīng)用場(chǎng)景
供客戶端模式下的HotSpot虛擬機(jī)使用
。- 在服務(wù)端模式下,一種在JDK 5以及之前的版本中
與Parallel Scavenge收集器搭配使用
;另外一種就是作為CMS收集器發(fā)生失敗時(shí)的后備預(yù)案
。
6. Parallel Old收集器
1. 簡(jiǎn)介
Parallel Old是Parallel Scavenge收集器的老年代版本
,支持多線程并發(fā)收集,基于標(biāo)記-整理算法實(shí)現(xiàn)。
2. 圖解工作過程
3. 使用的垃圾收集算法
標(biāo)記-整理算法
4. 主要的應(yīng)用場(chǎng)景
注重吞吐量或者處理器資源較為稀缺的場(chǎng)合
,都可以優(yōu)先考慮Parallel Scavenge 加 Parallel Old收集器這個(gè)組合。
7. CMS收集器
1. 簡(jiǎn)介
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)
的收集器。CMS收集器是基于標(biāo)記-清除算法
實(shí)現(xiàn)的。它非常適合在注重用戶體驗(yàn)的應(yīng)用上使用
。
2. 工作過程
- 初始標(biāo)記:
標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象
,速度很快 - 并發(fā)標(biāo)記:從GC Roots的直接關(guān)聯(lián)對(duì)象開始遍歷整個(gè)對(duì)象圖的過程,這個(gè)過程耗時(shí)較長(zhǎng)但是
不需要停頓用戶線程
,用戶線程可以與垃圾收集線程一起并發(fā)運(yùn)行。
- 重新標(biāo)記:為了
修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄
,這個(gè)階段的停頓時(shí)間通常會(huì)比初始標(biāo)記階段稍長(zhǎng)一些,但也遠(yuǎn)比并發(fā)標(biāo)記階段的時(shí)間短。 - 并發(fā)清除:
清理刪除掉標(biāo)記階段判斷的已經(jīng)死亡的對(duì)象
,由于不需要移動(dòng)存活對(duì)象,所以這個(gè)階段也是可以與用戶線程同時(shí)并發(fā)的。
3. 圖解工作過程
4. 使用的垃圾收集算法
標(biāo)記-清除算法
。
5. 優(yōu)點(diǎn)
回收停頓時(shí)間短
,給用戶帶來良好的交互體驗(yàn)。并發(fā)收集
6. 缺點(diǎn)
對(duì)處理器資源非常敏感
無法處理“浮動(dòng)垃圾”
- 因?yàn)镃MS收集器是一款基于標(biāo)記-清除算法的垃圾收集器,
其收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生
。
7. 主要的應(yīng)用場(chǎng)景
它非常適合在注重用戶體驗(yàn)和要求停頓時(shí)間短的應(yīng)用上使用
。
8. Garbage First收集器
1. 簡(jiǎn)介
G1 (Garbage-First) 是一款面向服務(wù)器的垃圾收集器
,主要針對(duì)配備多顆處理器及大容量?jī)?nèi)存的機(jī)器。以極高概率滿足 GC 停頓時(shí)間要求
的同時(shí),還具備高吞吐量性能特征
。G1在后臺(tái)維護(hù)一個(gè)優(yōu)先級(jí)列表,每次根據(jù)用戶設(shè)定允許的收集停頓時(shí)間,優(yōu)先處理回收價(jià)值收益最大的那些Region
。這種使用 Region劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了 G1 收集器在有限時(shí)間內(nèi)可以盡可能高的收集效率(把內(nèi)存化整為零)。
2. 工作過程
- 初始標(biāo)記:僅僅
只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象
,并且修改TAMS指針的值,讓下一階段用戶線程并發(fā)運(yùn)行時(shí),能正確地在可用的Region中分配新對(duì)象。這個(gè)階段需要停頓線程,但耗時(shí)很短
,而且是借用進(jìn)行Minor GC的時(shí)候同步完成的,所以G1收集器在這個(gè)階段實(shí)際并沒有額外的停頓。 - 并發(fā)標(biāo)記:從GC Root開始對(duì)堆中對(duì)象進(jìn)行可達(dá)性分析,遞歸掃描整個(gè)堆里的對(duì)象圖,
找出要回收的對(duì)象
,這階段耗時(shí)較長(zhǎng),但可與用戶程序并發(fā)執(zhí)行
。當(dāng)對(duì)象圖掃描完成以后,還要重新處理SATB記錄下的在并發(fā)時(shí)有引用變動(dòng)的對(duì)象。最終標(biāo)記:對(duì)用戶線程做另一個(gè)短暫的暫停,用于處理并發(fā)階段結(jié)束后仍遺留下來的最后那少量的SATB記錄
。 - 篩選回收:負(fù)責(zé)更新Region的統(tǒng)計(jì)數(shù)據(jù),
對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序
,根據(jù)用戶所期望的停頓時(shí)間來制定回收計(jì)劃,可以自由選擇任意多個(gè)Region構(gòu)成回收集,然后把決定回收的那一部分Region的存活對(duì)象復(fù)制到空的Region中
,再清理掉整個(gè)舊Region的全部空間
。這里的操作涉及存活對(duì)象的移動(dòng),是必須暫停用戶線程,由多條收集器線程并行完成的。
從上述階段的描述可以看出,G1收集器除了并發(fā)標(biāo)記外,其余階段也是要完全暫停用戶線程的,換言之,它
并非純粹地追求低延遲
,官方給它設(shè)定的目標(biāo)是在延遲可控的情況下獲得盡可能高的吞吐量
,所以才能擔(dān)當(dāng)起“全功能收集器”的重任與期望。
3. 圖解工作過程
4. 特點(diǎn)
- 并行與并發(fā):
- 分代收集
- 空間整合
- 可預(yù)測(cè)的停頓
5. 使用此收集器下的堆內(nèi)存說明
G1不再堅(jiān)持固定大小以及固定數(shù)量的分代區(qū)域劃分,而是把連續(xù)的Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region)
,每一個(gè)Region都可以根據(jù)需要,扮演新生代的Eden空間、Survivor空間,或者老年代空間
。收集器能夠?qū)Π缪莶煌巧腞egion采用不同的策略去處理,這樣無論是新創(chuàng)建的對(duì)象還是已經(jīng)存活了一段時(shí)間、熬過多次收集的舊對(duì)象都能獲取很好的收集效果。Region中還有一類特殊的Humongous區(qū)域(H),專門用來存儲(chǔ)大對(duì)象
。G1認(rèn)為只要大小超過了一個(gè)Region容量一半的對(duì)象即可判定為大對(duì)象。每個(gè)Region的大小可以通過參數(shù)-XX:G1HeapRegionSize
設(shè)定,取值范圍為1MB~32MB,且應(yīng)為2的N次冪。而對(duì)于那些超過了整個(gè)Region容量的超級(jí)大對(duì)象
,將會(huì)被存放在N個(gè)連續(xù)的Humongous Region之中
,G1的大多數(shù)行為都把Humongous Region作為老年代的一部分
來進(jìn)行看待,如上圖所示。雖然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它們都是一系列區(qū)域(不需要連續(xù))的動(dòng)態(tài)集合
。
6. 主要的應(yīng)用場(chǎng)景
主要使用于服務(wù)端模式下的垃圾回收
。
到此這篇關(guān)于深入理解Java虛擬機(jī)之經(jīng)典垃圾收集器的文章就介紹到這了,更多相關(guān)java垃圾收集器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
超詳細(xì)講解Java秒殺項(xiàng)目用戶驗(yàn)證模塊的實(shí)現(xiàn)
這是一個(gè)主要使用java開發(fā)的秒殺系統(tǒng),項(xiàng)目比較大,所以本篇只實(shí)現(xiàn)了用戶驗(yàn)證模塊,代碼非常詳盡,感興趣的朋友快來看看2022-03-03Java操作Elasticsearch?rest-high-level-client?的基本使用
這篇文章主要介紹了Java操作Elasticsearch?rest-high-level-client?的基本使用,本篇主要講解一下?rest-high-level-client?去操作?Elasticsearch的方法,結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下2022-10-10深度剖析Java成員變量、局部變量和靜態(tài)變量的創(chuàng)建和回收時(shí)機(jī)
這篇文章主要介紹了深度剖析Java成員變量、局部變量和靜態(tài)變量的創(chuàng)建和回收時(shí)機(jī),成員變量是定義在類中的變量,每個(gè)類的實(shí)例都會(huì)擁有自己的成員變量。它們的生命周期與對(duì)象的創(chuàng)建和銷毀相對(duì)應(yīng),下面我將詳細(xì)介紹它們的特點(diǎn)和生命周期,需要的朋友可以參考下2023-07-07Runtime.getRuntime().exec 路徑包含空格的解決
這篇文章主要介紹了Runtime.getRuntime().exec 路徑包含空格的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Java實(shí)現(xiàn)商品的查找、添加、出庫、入庫操作完整案例
這篇文章主要介紹了Java實(shí)現(xiàn)商品的查找、添加、出庫、入庫操作,結(jié)合完整實(shí)例形式分析了java基于面向?qū)ο蟮纳唐沸畔⑻砑?、刪除、查找等相關(guān)操作技巧,需要的朋友可以參考下2019-11-11java實(shí)現(xiàn)電話本管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了JAVA實(shí)現(xiàn)電話本管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02Java使用SFTP上傳文件到服務(wù)器的簡(jiǎn)單使用
這篇文章主要介紹了Java使用SFTP上傳文件到服務(wù)器的簡(jiǎn)單使用,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02