Java中的垃圾收集器詳解
Serial
Serial(串行)收集器收集器是最基本、歷史最悠久的垃圾收集器了。
大家看名字就知道這個(gè)收集器是一個(gè)單線程收集器了。它的 “單線程” 的意義不僅僅意味著它只會(huì)使用一條垃圾收集線程去完成垃圾收集工作,更重要的是它在進(jìn)行垃圾收集工作的時(shí)候必須暫停其他所有的工作線程( "Stop The World" ),直到它收集結(jié)束。
新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。
虛擬機(jī)的設(shè)計(jì)者們當(dāng)然知道 Stop The World 帶來的不良用戶體驗(yàn),所以在后續(xù)的垃圾收集器設(shè)計(jì)中停頓時(shí)間在不斷縮短(仍然還有停頓,尋找最優(yōu)秀的垃圾收集器的過程仍然在繼續(xù))。
但是 Serial 收集器有沒有優(yōu)于其他垃圾收集器的地方呢?當(dāng)然有,它簡單而高效(與其他收集器的單線程相比)。Serial 收集器由于沒有線程交互的開銷,自然可以獲得很高的單線程收集效率。Serial 收集器對(duì)于運(yùn)行在 Client 模式下的虛擬機(jī)來說是個(gè)不錯(cuò)的選擇。
ParNew
ParNew 收集器其實(shí)就是 Serial 收集器的多線程版本,除了使用多線程進(jìn)行垃圾收集外,其余行為(控制參數(shù)、收集算法、回收策略等等)和 Serial 收集器完全一樣。
新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。
它是許多運(yùn)行在 Server 模式下的虛擬機(jī)的首要選擇,除了 Serial 收集器外,只有它能與 CMS 收集器(真正意義上的并發(fā)收集器,后面會(huì)介紹到)配合工作。
并行和并發(fā)概念補(bǔ)充:
- 并行(Parallel) :指多條垃圾收集線程并行工作,但此時(shí)用戶線程仍然處于等待狀態(tài)。
- 并發(fā)(Concurrent):指用戶線程與垃圾收集線程同時(shí)執(zhí)行(但不一定是并行,可能會(huì)交替執(zhí)行),用戶程序在繼續(xù)運(yùn)行,而垃圾收集器運(yùn)行在另一個(gè) CPU 上。
Parallel Scavenge
Parallel Scavenge 收集器也是使用復(fù)制算法的多線程收集器,它看上去幾乎和ParNew都一樣。
那么它有什么特別之處呢?
-XX:+UseParallelGC 使用 Parallel 收集器+ 老年代串行 -XX:+UseParallelOldGC 使用 Parallel 收集器+ 老年代并行
Parallel Scavenge 收集器關(guān)注點(diǎn)是吞吐量(高效率的利用 CPU)。
CMS 等垃圾收集器的關(guān)注點(diǎn)更多的是用戶線程的停頓時(shí)間(提高用戶體驗(yàn))。
所謂吞吐量就是 CPU 中用于運(yùn)行用戶代碼的時(shí)間與 CPU 總消耗時(shí)間的比值。
Parallel Scavenge 收集器提供了很多參數(shù)供用戶找到最合適的停頓時(shí)間或最大吞吐量,如果對(duì)于收集器運(yùn)作不太了解的話,手工優(yōu)化存在困難的話可以選擇把內(nèi)存管理優(yōu)化交給虛擬機(jī)去完成也是一個(gè)不錯(cuò)的選擇。
新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法。
Serial old
Serial 收集器的老年代版本,它同樣是一個(gè)單線程收集器。
它主要有兩大用途:
- 一種用途是在 JDK1.5 以及以前的版本中與 Parallel Scavenge 收集器搭配使用
- 另一種用途是作為 CMS 收集器的后備方案。
Parallel old
Parallel Scavenge 收集器的老年代版本。
使用多線程和“標(biāo)記-整理”算法。
在注重吞吐量以及 CPU 資源的場合,都可以優(yōu)先考慮 Parallel Scavenge 收集器和 Parallel Old 收集器。
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。
它非常符合在注重用戶體驗(yàn)的應(yīng)用上使用。
CMS(Concurrent Mark Sweep)收集器是 HotSpot 虛擬機(jī)第一款真正意義上的并發(fā)收集器,它第一次實(shí)現(xiàn)了讓垃圾收集線程與用戶線程(基本上)同時(shí)工作。
從名字中的Mark Sweep這兩個(gè)詞可以看出,CMS 收集器是一種 “標(biāo)記-清除”算法實(shí)現(xiàn)的,它的運(yùn)作過程相比于前面幾種垃圾收集器來說更加復(fù)雜一些。
整個(gè)過程分為四個(gè)步驟:
- 初始標(biāo)記: 暫停所有的其他線程,并記錄下直接與 root 相連的對(duì)象,速度很快 ;
- 并發(fā)標(biāo)記: 同時(shí)開啟 GC 和用戶線程,用一個(gè)閉包結(jié)構(gòu)去記錄可達(dá)對(duì)象。但在這個(gè)階段結(jié)束,這個(gè)閉包結(jié)構(gòu)并不能保證包含當(dāng)前所有的可達(dá)對(duì)象。因?yàn)橛脩艟€程可能會(huì)不斷的更新引用域,所以 GC 線程無法保證可達(dá)性分析的實(shí)時(shí)性。所以這個(gè)算法里會(huì)跟蹤記錄這些發(fā)生引用更新的地方。
- 重新標(biāo)記: 重新標(biāo)記階段就是為了修正并發(fā)標(biāo)記期間因?yàn)橛脩舫绦蚶^續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間一般會(huì)比初始標(biāo)記階段的時(shí)間稍長,遠(yuǎn)遠(yuǎn)比并發(fā)標(biāo)記階段時(shí)間短
- 并發(fā)清除: 開啟用戶線程,同時(shí) GC 線程開始對(duì)為標(biāo)記的區(qū)域做清掃。
從它的名字就可以看出它是一款優(yōu)秀的垃圾收集器
主要優(yōu)點(diǎn):
- 并發(fā)收集
- 低停頓
但是它有下面三個(gè)明顯的缺點(diǎn):
- 對(duì) CPU 資源敏感;
- 無法處理浮動(dòng)垃圾;
- 它使用的回收算法-“標(biāo)記-清除”算法會(huì)導(dǎo)致收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生。
G1收集器
G1 (Garbage-First) 是一款面向服務(wù)器的垃圾收集器,主要針對(duì)配備多顆處理器及大容量內(nèi)存的機(jī)器。以極高概率滿足 GC 停頓時(shí)間要求的同時(shí),還具備高吞吐量性能特征。
被視為 JDK1.7 中 HotSpot 虛擬機(jī)的一個(gè)重要進(jìn)化特征。
它具備以下特點(diǎn):
- 并行與并發(fā):G1 能充分利用 CPU、多核環(huán)境下的硬件優(yōu)勢,使用多個(gè) CPU(CPU 或者 CPU 核心)來縮短 Stop-The-World 停頓時(shí)間。部分其他收集器原本需要停頓 Java 線程執(zhí)行的 GC 動(dòng)作,G1 收集器仍然可以通過并發(fā)的方式讓 java 程序繼續(xù)執(zhí)行。
- 分代收集:雖然 G1 可以不需要其他收集器配合就能獨(dú)立管理整個(gè) GC 堆,但是還是保留了分代的概念。
- 空間整合:與 CMS 的“標(biāo)記--清理”算法不同,G1 從整體來看是基于“標(biāo)記整理”算法實(shí)現(xiàn)的收集器;從局部上來看是基于“復(fù)制”算法實(shí)現(xiàn)的。
- 可預(yù)測的停頓:這是 G1 相對(duì)于 CMS 的另一個(gè)大優(yōu)勢,降低停頓時(shí)間是 G1 和 CMS 共同的關(guān)注點(diǎn),但 G1 除了追求低停頓外,還能建立可預(yù)測的停頓時(shí)間模型,能讓使用者明確指定在一個(gè)長度為 M 毫秒的時(shí)間片段內(nèi)。
G1 收集器的運(yùn)作大致分為以下幾個(gè)步驟:
- 初始標(biāo)記
- 并發(fā)標(biāo)記
- 最終標(biāo)記
- 篩選回收
G1 收集器在后臺(tái)維護(hù)了一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先選擇回收價(jià)值最大的 Region(這也就是它的名字 Garbage-First 的由來)。
這種使用 Region 劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了 GF 收集器在有限時(shí)間內(nèi)可以盡可能高的收集效率(把內(nèi)存化整為零)。
到此這篇關(guān)于Java中的垃圾收集器詳解的文章就介紹到這了,更多相關(guān)Java垃圾收集器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于application.yml基礎(chǔ)配置以及讀取方式
這篇文章主要介紹了關(guān)于application.yml基礎(chǔ)配置以及讀取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07基于spring?data?jpa?@query返回map的踩坑記錄
這篇文章主要介紹了基于spring?data?jpa?@query返回map的踩坑記錄,具有很好的參考價(jià)值,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11RocketMQ源碼解析topic創(chuàng)建機(jī)制詳解
這篇文章主要為大家介紹了RocketMQ源碼解析topic創(chuàng)建機(jī)制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08淺談shiro的SecurityManager類結(jié)構(gòu)
下面小編就為大家?guī)硪黄獪\談shiro的SecurityManager類結(jié)構(gòu)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07