前言
感謝讀者的反饋嘁灯,在??圖中更新了新生代Eden區(qū)以及兩個(gè)Survivor區(qū)的默認(rèn)空間占比的分配表示弟头,這里按照10等份區(qū)分8/10纲爸、1/10褥琐、1/10分別表示8:1:1的關(guān)系,會更清晰點(diǎn)炭臭。新生代所采用的“標(biāo)記-復(fù)制-清除”的算法進(jìn)行垃圾回收永脓,以及分代回收算法中老年代如何為這種空間分配比所提供擔(dān)保策略,在前文《一張圖讓你看懂JVM之垃圾回收算法詳解》中有比較詳細(xì)的敘述鞋仍,大家可以看下常摧,這里就不再贅述。
另外一個(gè)遺留問題是關(guān)于direct memory和n****ative momery區(qū)別的問題威创,首先可以確認(rèn)的是這兩種稱呼的內(nèi)存肯定都是堆外內(nèi)存落午,是不受JVM自動垃圾回收機(jī)制管理的。
從更為細(xì)致的角度區(qū)分肚豺,目前有一種解釋是這樣表述的:"direct memory溃斋,在Java的上下文中特指Java程序通過一組特定的API訪問native memory,而這組API主要是通過DirectByteBuffer暴露出來的吸申。而Native memory則是一個(gè)相對通用的概念梗劫,因?yàn)樵贖otspot VM中,不受GC管理的內(nèi)存都是native memory,direct memory只限定在特定的訪問Native memory的做法截碴,二者并不完全等價(jià)"梳侨。關(guān)于這個(gè)兩個(gè)概念的解釋,如果有更好的區(qū)分大家可以給我留言日丹,這個(gè)問題實(shí)際上并不關(guān)鍵走哺,只是有同學(xué)有疑問,這里就稍微解釋下了哲虾。
回到本文的主題丙躏,在之前文章中我們對Java垃圾收集算法的特點(diǎn)有了一定的認(rèn)識齐帚,但是對于JVM而言算法并不是實(shí)現(xiàn),要進(jìn)行GC操作JVM是通過特定的垃圾回收器來完成的彼哼,在??圖中已經(jīng)把目前比較常用的垃圾回收器对妄,以及這些回收器分別適用于那些內(nèi)存空間作了一個(gè)初步的展示,但是這些垃圾回收器的特點(diǎn)是什么敢朱?有什么樣的優(yōu)缺點(diǎn)剪菱?在本文中和大家探討下。
垃圾回收器
垃圾收集器是垃圾收集算法的具體實(shí)現(xiàn)拴签,由于Java虛擬機(jī)規(guī)范并沒有對垃圾收集器如何實(shí)現(xiàn)進(jìn)行明確的規(guī)定孝常,所以不同的JVM廠商以及不同虛擬機(jī)版本所提供的垃圾收集器都可能會有較大的差別,并且一般也都會提供對應(yīng)的參數(shù)蚓哩,供用戶根據(jù)自己的應(yīng)用特點(diǎn)組合出各個(gè)內(nèi)存區(qū)塊构灸,主要是新生代、老年代所使用的收集器岸梨。
本文以JDK1.7 Update14之后的Hotspot虛擬機(jī)喜颁,也是目前使用最為廣泛的虛擬機(jī)為基礎(chǔ),和大家一起看看都有那些垃圾收集器曹阔,以及它們的特點(diǎn)是什么半开。
在詳細(xì)討論具體垃圾收集器之前,我們先看下這些收集器所適用的范圍赃份,以及它們的組合配對關(guān)系寂拆。
具體如下圖所示:
上圖展示了JDK1.7+后,Hotspot JVM的所有垃圾收集器以及它們適用的“代”,適合新生代的垃圾收集器有:Serial抓韩、ParNew纠永、Parallel Scavenge、G1谒拴。適合年老代的垃圾收集器有:CMS尝江、Serial Old、Parallel Old彪薛、G1茂装。它們之間的組合關(guān)系如上圖連線(粗線相連的是最佳組合)怠蹂,其中G1是JDK1.7 Update14這個(gè)版本中正式提供的商業(yè)收集器善延,它可以同時(shí)適用于新生代和年老代。
實(shí)踐上在JDK1.7以后其實(shí)是可以統(tǒng)一采用G1收集器的(作者目前所在公司已經(jīng)全部使用G1收集器)城侧,至于G1具體的特性易遣,在本文稍后的內(nèi)容中詳細(xì)講解。
- JAVA_OPTS=-Xms4g -Xmx4g -Xmn2g -XX:MaxDirectMemorySize=1g -XX:-
OmitStackTraceInFastThrow -XX:+UseG1GC -XX:G1ReservePercent=25 -
XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=8 -
XX:+DisableExplicitGC -verbose:gc -Xloggc:/opt/gc_%p.log -XX:+PrintGCDetails -
XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -
XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m
雖然實(shí)踐上已然可以同一采用G1了嫌佑,但是作為基礎(chǔ)知識豆茫,我們還是對這些具體垃圾收集器有一個(gè)比較深刻的認(rèn)識會比較好侨歉。下面就依次討論下這些垃圾收集器的特點(diǎn)是什么吧!
Serial(新生代-串行-收集器)
Serial是一個(gè)比較古老的收集器揩魂,而且是一個(gè)單線程的收集器幽邓,這種收集器在進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程火脉,直到它收集結(jié)束(采用的是復(fù)制算法)牵舵。所以試想下在互聯(lián)網(wǎng)高并發(fā)的場景下采用這樣的收集器顯然是不可以的,所以我們目前在做后端服務(wù)時(shí)倦挂,不可能會用到這款收集器畸颅。
因?yàn)槠浜唵巍尉€程的特點(diǎn)用在Java桌面程序場景會比較合適方援,但是大家也都知道目前采用Java開發(fā)桌面程序已經(jīng)很少見了没炒,所以大家對此了解就行。
其工作示意圖如下:
ParNew(新生代-并行-收集器)
Parnew收集器是Serial的多線程版本犯戏,除了多線程收集外送火,其余部分與Serial相比并沒有多大的差別,由于其可以與CMS收集器配合使用先匪,所以在JDK1.7之前漾脂,對于Java服務(wù)應(yīng)用來說是首選的新生代收集器。
示意圖如下:
這種收集器與Serial一樣胚鸯,在進(jìn)行垃圾回收時(shí)也會暫停所有用戶工作線程骨稿,只是它采取了多線程回收,所以回收的速度會比Serial快姜钳,從而將卡頓時(shí)間縮短坦冠。
Parallel Scavenge (新生代-并行-收集器)
Parallel Scavenge也是一個(gè)新生代收集器,采用的也是多線程哥桥,以及復(fù)制收集算法辙浑,與其他同類型收集器不同的是,它的關(guān)注點(diǎn)是達(dá)到一個(gè)可控制吞吐量的目標(biāo)拟糕,吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾回收的時(shí)間)判呕,假設(shè)虛擬機(jī)總共運(yùn)行了100分鐘,其中垃圾回收花了一分鐘送滞,那么吞吐量就是99%侠草。高吞吐量的目的是為了高效的利用CPU時(shí)間,從而盡快的完成程序運(yùn)算任務(wù)犁嗅,主要適合后臺運(yùn)算不需要有太多交互的應(yīng)用場景边涕。
該收集器提供的控制參數(shù)有:
? MaxGCPauseMillis:GC時(shí)間的最大值。
? GCTimeRatio:GC時(shí)間占用總時(shí)間的比例。
? UseAdaptiveSizePolicy:這個(gè)參數(shù)則是開啟GC內(nèi)存分配的自適應(yīng)調(diào)整策略功蜓≡耙可以自動調(diào)節(jié),新生代的大小式撼、Eden與Survivor的比例童社、晉升老年代對象的年齡。
Serial Old(年老代-串行-收集器)
Serial Old 收集器就是Serial的老年代版本著隆,是一個(gè)單線程的叠洗,垃圾收集算法采用標(biāo)記-整理算法的收集器。
Parallel Old(年老代-并行-收集器)
Parallel Old收集器是Parallel Scavenge的老年代版本旅东,是多線程灭抑,采用標(biāo)記-整理算法的收集器。
CMS(年老代-并行-收集器)
CMS(Concurrent Mark-Sweep)是一款以獲取最短回收停頓時(shí)間為目標(biāo)的收集器抵代。比較適合互聯(lián)網(wǎng)響應(yīng)式應(yīng)用場景腾节,采用的是“標(biāo)記-清除”算法。
其收集過程如下圖所示:
如圖所示荤牍,在初始標(biāo)記和重新標(biāo)記兩個(gè)步驟案腺,也會和Serial 一樣暫停所有用戶線程。
G1收集器
G1(Garbage First)是目前最為前沿的垃圾回收器康吵,在前面的內(nèi)容中已經(jīng)提過JDK1.8以后的生產(chǎn)實(shí)踐新生代劈榨、年老代都可以采用G1作為垃圾回收器。其采用的收集算法是”標(biāo)記-清除-整理“晦嵌,所以不會產(chǎn)生內(nèi)存碎片同辣。
后記
在實(shí)踐中關(guān)于GC收集器的選擇,看目前來看惭载,如果是互聯(lián)網(wǎng)高并發(fā)場景的服務(wù)器端應(yīng)用旱函,可以統(tǒng)一使用G1就行。而如果是其他的應(yīng)用場景描滔,可能就需要根據(jù)合適的場景進(jìn)行組合選擇了棒妨。