1、垃圾收集器種類
事實(shí)上Java虛擬機(jī)規(guī)范對垃圾收集器應(yīng)該如何實(shí)現(xiàn),并沒有任何的規(guī)定,所以不同的廠商、不同版本的虛擬機(jī)所提供的垃圾收集器都會(huì)有所不同,并且一般都會(huì)提供參數(shù)供用戶根據(jù)自己的應(yīng)用特點(diǎn)和要求組合出各個(gè)年代所使用的收集器。
下圖是基于 Sun HotSpot 虛擬機(jī)1.6版 Update 22的虛擬機(jī)種類:
由上圖我們可以總結(jié)出幾個(gè)結(jié)論:
①、新生代垃圾收集器:Serial、ParNew、Parallel Scavenge;
老年代垃圾收集器:Serial Old(MSC)、Parallel Old、CMS;
整堆垃圾收集器:G1
②、垃圾收集器之間的連線表示可以搭配使用,有如下幾種組合:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;
③、串行收集器Serial:Serial、Serial Old
并行收集器 Parallel:Parallel Scavenge、Parallel Old
并發(fā)收集器:CMS、G1
2、Serial收集器
這是一個(gè)最基本,歷史最悠久的垃圾收集器,是JDK1.3之前新生代唯一的垃圾收集器。
該收集器有如下特點(diǎn):
①、作用于新生代
由上圖也可看出,這是一個(gè)新生代垃圾收集器,采用的垃圾回收算法是復(fù)制算法。
②、單線程
工作時(shí)只會(huì)使用一個(gè)CPU或者一條收集線程去完成工作。
③、進(jìn)行垃圾收集時(shí),必須暫停所有工作線程
也就是說使用Serial收集器進(jìn)行垃圾回收時(shí),別的工作線程都暫停,系統(tǒng)這時(shí)候會(huì)有卡頓現(xiàn)象產(chǎn)生。
④、適用場景
Serial 收集器由于沒有線程交互的開銷,對于限定單個(gè)CPU的環(huán)境,可以獲得最高的單線程收集效率。
一般在用戶的桌面場景中,分配給虛擬機(jī)管理的內(nèi)存一般來說不會(huì)很大,收集幾十兆或一兩百兆的新生代,定頓時(shí)間可以控制在幾十毫秒,只要不是頻繁發(fā)生的,這點(diǎn)停頓是可以接受的。
所以 Serial 收集器對于運(yùn)行在 Client 模式下的虛擬機(jī)是一種很好的選擇。
3、ParNew收集器
這個(gè)收集器其實(shí)就是Serial收集器的多線程版本。
也就是說其特點(diǎn)除了多線程,其余和Serial收集器一樣,事實(shí)上,這兩個(gè)收集器實(shí)現(xiàn)上也共用了很多代碼。
①、作用于新生代
一個(gè)新生代垃圾收集器,采用的垃圾回收算法是復(fù)制算法。
②、多線程
彌補(bǔ)了Serial收集器單線程的缺陷。
③、適用場景
由于其多線程的特性,是大多數(shù)運(yùn)行在 Server 模式下的虛擬機(jī)首選新生代垃圾收集器。
另外需要說明的是,能夠與下面將要介紹的劃時(shí)代垃圾收集器CMS(Concurrent Mark Sweep)配合使用,也是一個(gè)重要原因。
4、Parallel Scavenge收集器
前面介紹的垃圾收集器關(guān)注點(diǎn)是盡可能縮小垃圾收集時(shí)的用戶線程停頓時(shí)間。而 Parallel Scanvenge 收集器是為了達(dá)到一個(gè)可控制的吞吐量。
吞吐量 = 運(yùn)行用戶代碼的時(shí)間 / (運(yùn)行用戶代碼的時(shí)間+垃圾收集時(shí)間)
可以用下面兩個(gè)參數(shù)進(jìn)行精確控制:
-XX:MaxGCPauseMills 設(shè)置最大垃圾收集停頓時(shí)間
-XX:GCTimeRatio 設(shè)置吞吐量大小
①、作用于新生代
一個(gè)新生代垃圾收集器,采用的垃圾回收算法是復(fù)制算法。
②、多線程
并行的多線程垃圾收集器。
③、吞吐量
這個(gè)收集器可以精確控制吞吐量。
④、適用場景
設(shè)置垃圾收集停頓時(shí)間短適合需要與用戶快速交互的程序;
而設(shè)置高吞吐量可以最高效的利用CPU效率,盡快的完成程序的運(yùn)算任務(wù),主要適合在后臺運(yùn)算而不需要太多交互的任務(wù)。
5、Serial Old收集器
Serial Old 收集器是 Serial 收集器的老年代版本,特點(diǎn)如下:
①、作用于老年代
②、單線程
③、使用標(biāo)記-整理算法
④、進(jìn)行垃圾收集時(shí),必須暫停所有工作線程
6、Parallel Old收集器
Parallel Old 是 Parallel Scavenge收集器的老年代版本,使用多線程和“標(biāo)記-整理”算法。
①、作用于老年代
②、多線程
③、使用標(biāo)記-整理算法
除了具有以上幾個(gè)特點(diǎn),比較關(guān)鍵的是能和新生代收集器 Parallel Scavenge 配置使用,獲得吞吐量最大化的效果。
7、CMS收集器
CMS,全稱為 Concurrent Mark Sweep ,顧名思義并發(fā)的,采用標(biāo)記-清除算法。另外也將這個(gè)收集器稱為并發(fā)低延遲收集器(Concurrent Low Pause Collector)
這是一款跨時(shí)代的垃圾收集器,真正做到了垃圾收集線程與用戶線程(基本上)同時(shí)工作。和 Serial 收集器的 Stop The World(媽媽打掃房間的時(shí)候,你不能再將垃圾丟到地上) 相比,真正做到了媽媽一邊打掃房間,你一邊丟垃圾。
①、作用于老年代
②、多線程
③、使用標(biāo)記-清除算法
整個(gè)算法過程分為如下 4 步:
一、初始標(biāo)記(CMS initial mark):只是僅僅標(biāo)記GC Root 能夠直接關(guān)聯(lián)的對象,速度很快,但是需要“Stop The World”
二、并發(fā)標(biāo)記(CMS concurrent mark):進(jìn)行GC Root Tracing的過程,簡單來說就是遍歷Initial Marking階段標(biāo)記出來的存活對象,然后繼續(xù)遞歸標(biāo)記這些對象可達(dá)的對象。
三、重新標(biāo)記(CMS Remark):修正并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對象的標(biāo)記記錄,需要“Stop The World”。這個(gè)時(shí)間一般比初始標(biāo)記長,但是遠(yuǎn)比并發(fā)標(biāo)記時(shí)間短。
四、并發(fā)清除(CMS concurrent sweep):對上一步標(biāo)記的對象進(jìn)行清除操作。
由于整個(gè)過程最耗時(shí)的操作是第二(并發(fā)標(biāo)記)、四步(并發(fā)清除),而這兩步垃圾收集器線程是可以和用戶線程一起工作的。所以整體來說,CMS垃圾收集和用戶線程是一起并發(fā)的執(zhí)行的。
缺點(diǎn):
①、對CPU資源敏感
因?yàn)樵诓l(fā)階段,會(huì)占用一部分CPU資源,從而導(dǎo)致應(yīng)用程序變慢,總吞吐量會(huì)降低。
②、產(chǎn)生浮動(dòng)垃圾
由于CMS并發(fā)清理階段用戶線程還在工作,這個(gè)時(shí)候產(chǎn)生的垃圾,CMS無法在本次收集中處理掉它們,只能留在下一次GC時(shí)再將其處理掉,這部分垃圾稱為“浮動(dòng)垃圾”。
③、產(chǎn)生內(nèi)存垃圾碎片
因?yàn)椴捎玫乃惴ㄊ菢?biāo)記-清除,很明顯,會(huì)有空間碎片產(chǎn)生。
8、G1收集器
這是當(dāng)前收集器技術(shù)發(fā)展的最前沿的成果??梢詫?shí)現(xiàn)在基本不犧牲吞吐量的前提下完成低停頓的內(nèi)存回收,首發(fā)于JDK8中,是JDK9默認(rèn)的垃圾回收器。
這是因?yàn)樗⒉幌袂懊娼榻B的所有垃圾收集器是區(qū)分新生代,老年代的,它作用于全區(qū)域。將整個(gè)Java堆劃分為多個(gè)大小固定的獨(dú)立區(qū)域(Regin),并且跟蹤這些區(qū)域的垃圾堆積面積,在后臺維護(hù)一個(gè)優(yōu)先級列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收垃圾最多的區(qū)域,這樣保證了G1收集器在有限的時(shí)間內(nèi)可以獲得最高的收集效率。
它與前面講的 CMS 垃圾收集器相比,有兩個(gè)顯著的改進(jìn):
①、采用 標(biāo)記-整理 的回收算法
這樣不會(huì)產(chǎn)生空間碎片
②、可以精確的控制停頓時(shí)間
能讓使用者明確指定一個(gè)長度為M毫秒的時(shí)間片內(nèi),消耗在垃圾回收上的時(shí)間不超過 N 毫秒。
③、作用于整個(gè)Java堆
G1收集器不區(qū)分年輕代和老年代,是整堆垃圾收集器。
9、ZGC 收集器
這是JDK11發(fā)布的一款垃圾收集器,是一個(gè)可擴(kuò)展的低延遲垃圾收集器,JDK17的默認(rèn)垃圾收集器,能用就用,性能絕對可以。有如下特性:
①、暫停時(shí)間不超過10毫秒
②、暫停時(shí)間不會(huì)隨堆或?qū)崟r(shí)設(shè)置大小而增加
③、處理堆范圍從幾百M(fèi)到幾TB。
10、如何選擇垃圾收集器
除非應(yīng)用程序有相當(dāng)嚴(yán)格的暫停時(shí)間要求,否則就讓JVM自己選擇垃圾收集器。并且可以適當(dāng)優(yōu)先調(diào)整堆的大小來提高性能。如果還不滿足要求,則以下面四點(diǎn)作為指導(dǎo):
- 如果應(yīng)用程序內(nèi)存小于100M,那么使用選項(xiàng)選擇串行收集器-XX:+UseSerialGC。
- 如果應(yīng)用程序?qū)⒃趩魏?a target="_blank">處理器上運(yùn)行,并且沒有停頓時(shí)間的要求,選擇串行-XX:+UseSerialGC或者 JVM 自己選
- 如果允許停頓時(shí)間超過1秒,選擇并行或 JVM 自己選
- 如果響應(yīng)時(shí)間比總吞吐量更重要,并且垃圾收集暫停必須保持短于大約1秒,則使用-XX:+UseConcMarkSweepGC或選擇并發(fā)收集器-XX:+UseG1GC。
當(dāng)然,現(xiàn)在無腦選擇ZGC,絕對沒錯(cuò)。
-
JAVA
+關(guān)注
關(guān)注
19文章
2967瀏覽量
104762 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
917瀏覽量
28207 -
JDK
+關(guān)注
關(guān)注
0文章
81瀏覽量
16597 -
收集器
+關(guān)注
關(guān)注
0文章
30瀏覽量
3140
發(fā)布評論請先 登錄
相關(guān)推薦
評論