幾種GC
Minor/Young GC: 只收集 Young區(qū)的 GC
每進行一次Young GC酱固,Survivor區(qū)內(nèi)活躍對象將加一歲氧腰,達到一定年齡將移入OLD區(qū)Old GC: 只收集 Old區(qū)的 GC痹升,只有垃圾收集器 CMS 的 concurrent collection 是這個模式
Full GC: 收集整個堆拒课,包括新生代鳞骤,老年代探颈,永久代(JDK1.8及以后為 metaspace 元空間)等所有部分的模式
Mixed GC: 收集整個 Young Gen 以及部分 old gen 的 GC,只有垃圾收集器 G1 有這個模式
GC時會stop the world
1症杏、避免無法徹底清理干凈
2装获、GC的工作必須在一個能確保一致性的快照中進行
申請內(nèi)存大致過程
1、創(chuàng)建對象后厉颤,將嘗試在Eden申請一片內(nèi)存
2穴豫、若Eden區(qū)內(nèi)存空間足夠,則申請結(jié)束
3逼友、若Eden區(qū)內(nèi)存空間不足精肃,進行YoungGC(觸發(fā)清理YOUNG區(qū)不活躍對象,活躍對象滿足一定條件的晉升到OLD區(qū))
4帜乞、若OLD的空間不足(觸發(fā)閾值或新晉對象等行為導(dǎo)致不足)則觸發(fā)FullGC
5司抱、若FullGC后,Eden區(qū)仍不能滿足申請的內(nèi)存挖函,則觸發(fā)OOM(out of memory)
GC收集算法(GC收集器都是基于這些算法來實現(xiàn))
復(fù)制(Copying)算法
YoungGC基本都是基于該算法状植,所以直接以YoungGC的過程來簡述該算法
假定正在使用的是S0區(qū),S1區(qū)是空閑的
將YOUNG區(qū)中活躍的對象復(fù)制到S1區(qū)(兩個Survivor區(qū)交替使用怨喘,永遠有一個是空的津畸,留給下次復(fù)制)并清理Eden區(qū)和S0區(qū)的對象。若活躍對象大于S1區(qū)時必怜,部分對象將會直接進入OLD區(qū)肉拓,部分仍留在S1區(qū)
缺點:浪費內(nèi)存
優(yōu)點:無內(nèi)存碎片,對象存活率低時效率高于另外幾種
適用:對象存活率低的
標(biāo)記-清除(Mark-Sweep)算法
從根開始標(biāo)記存活的對象梳庆,然后重新掃一遍將未標(biāo)記的對象清除同時清除標(biāo)記
缺點:
產(chǎn)生大量內(nèi)存碎片暖途,容易導(dǎo)致大內(nèi)存對象無足夠空間,提前觸發(fā)GC
效率低(全堆對象遍歷)stop the world的時間比較長
標(biāo)記-整理(Mark-Compact)算法
從根開始標(biāo)記存活的對象膏执,然后整理到一端驻售,其余清除
缺點:效率低(全堆對象遍歷與內(nèi)存整理)
優(yōu)點:有效利用內(nèi)存無碎片
年輕代一般適用復(fù)制算法,年老代一般適用標(biāo)記-整理算法
GC的幾種收集器
年輕代收集器
Serial
這是最早的新生代收集器更米,也是jdk1.5之前默認(rèn)的收集器欺栗。它是基于復(fù)制算法實現(xiàn)的,單線程征峦,需要stop the world迟几,所以新生代不能太大,否則對于停頓來講是比較影響交互響應(yīng)的栏笆。
-XX:+UseSerialGC 使用該收集器
Parallel New
-XX:ParallelGCThreads=NNN 來指定 GC 線程數(shù)类腮。 其默認(rèn)值為CPU內(nèi)核數(shù)。
這是對單線程的Serial的一種改進蛉加,ParNew收集器是并行的蚜枢,在多CPU的場景下會有比串行收集器更好的性能,除此之外针饥,實現(xiàn)算法跟Serial完全一樣祟偷。需要注意的是,如果CPU數(shù)量為1個或2個打厘,該種收集器的性能并不會比Serial要好修肠,因為線程之間的切換會產(chǎn)生額外的開銷
Parallel Scavenge
-XX:MaxGCPauseMillis
控制垃圾收集最大停頓時間(毫秒),收集器將盡力保證內(nèi)存回收花費的時間不超過設(shè)定值(設(shè)置過小會導(dǎo)致新生代空間變小户盯,導(dǎo)致GC更頻繁嵌施,總GC時間反而變長、吞吐量下降)
-XX:GCTimeRatio
設(shè)置吞吐量大忻а肌(0-100)吗伤,GC時間 <= 1 / (1 + 吞吐量) * 的系統(tǒng)運行花時間。(-XX:GCTimeRatio=99硫眨,表示GC時間不超過總時間的1%)
-XX:+UseAdaptiveSizePolicy
自適應(yīng)策略開關(guān)開關(guān)參數(shù)足淆,不需要手工指定(-Xmn,-XX:SurvivorRatio、-XX:PretenureSizeThreshold)等細節(jié)參數(shù)了巧号,虛擬機會根據(jù)當(dāng)前系統(tǒng)的運行情況收集性能監(jiān)控信息族奢,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或最大的吞吐量
采用的也是復(fù)制算法,它與前兩種收集器最大的區(qū)別是丹鸿,它關(guān)注的是吞吐量而不是延遲越走。也被稱為是吞吐量優(yōu)先的收集器。其中靠欢,吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
主要使用場景:主要適合在后臺運算而不是太多交互的任務(wù)廊敌,高吞吐量則可以最高效率的利用CPU時間,盡快的完成程序的運算任務(wù)
年老代收集器
Serial Old
這個是jdk1.2以前的默認(rèn)收集器,使用的是【標(biāo)記-整理】算法门怪,單線程骡澈,stop the world
Parallel Old
Parallel Scavenge的老年代版本,使用的是【標(biāo)記-整理】算法掷空。目前它跟Parallel Scavenge的配合是吞吐量優(yōu)先場景的優(yōu)先選擇秧廉。
CMS
-XX:+UseCMSCompactAtFullCollection,應(yīng)用于在FULL GC后再進行一個碎片整理過程
-XX:+CMSFullGCsBeforeCompaction拣帽,多少次不壓縮的full gc后來一次帶壓縮的
-XX:+UseCMSInitiatingOccupancyOnly=true疼电,使用手動指定回收百分比
-XX:CMSInitiatingOccupancyFraction=92,對內(nèi)存占用率達到92%提前GC(因為CMS產(chǎn)生浮動垃圾)
CMS减拭,Concurrent Mark Sweep蔽豺,這是一款真正的并發(fā)收集器。前面的都是講的并行拧粪。使用的是【標(biāo)記-清除】算法
收集過程:
1修陡、初始標(biāo)記,stop the world可霎,只做GC Root可達性的初始標(biāo)記
2魄鸦、并發(fā)標(biāo)記,并發(fā)執(zhí)行癣朗,進行GCRoots Tracing(可達性分析)過程拾因,時間很長
3、重新標(biāo)記旷余,stop the world绢记,標(biāo)記第二步中變動的對象,時間較長
4正卧、并發(fā)清除蠢熄,并發(fā)執(zhí)行,回收內(nèi)存空間
缺點:
內(nèi)存碎片炉旷,提前觸發(fā)一次full gc
產(chǎn)生浮動垃圾签孔,由于清除是并發(fā)的叉讥,這時用戶產(chǎn)生的垃圾無法在本次收集過程中收集掉
收集器 G1
-XX:+UseG1GC,使用G1收集器
-XX:G1HeapRegionSize饥追,一個Region的大小2的冪
-XX:MaxGCPauseMillis图仓,期望GC停頓時間(毫秒)
-XX:ParallelGCThreads,并行STW的線程數(shù)(與邏輯處理器的數(shù)量相同)
-XX:ConcGCThreads判耕,并行標(biāo)記的線程數(shù)(ParallelGCThreads的1/4)
-XX:InitiatingHeapOccupancyPercent=60,YoungGC后當(dāng)整個堆占用超過60%時翘骂,就會觸發(fā)并發(fā)GC周期
-XX:G1HeapWastePercent=10壁熄,并發(fā)標(biāo)記后可回收的垃圾占比,小于則不回收碳竟,10%
-XX:G1MixedGCCountTarget=8草丧,一個周期內(nèi)觸發(fā)Mixed GC最大次數(shù),8次
-XX:G1NewSizePercent=35莹桅,新生代比例下限昌执,35%
-XX:G1MaxNewSizePercent=60,新生代比例上限诈泼,60%
-XX:MetaspaceSize=256m
G1收集器將內(nèi)存劃分了多個區(qū)域(Region)
區(qū)域的類型有Eden懂拾,Survivor,Old铐达,Humongous岖赋,除了Humongous外,其余和之前介紹的一樣意思
Humongous:用于存放巨型對象(超過Region大小的50%)瓮孙,若一個存不下將找多個連續(xù)的Humongous一起唐断。一開始直接存在Old的空間,但G1有優(yōu)化會在YoungGC對其進行回收(從1.8的某個版本開始)
YoungGC
回收Eden杭抠、Survivor脸甘、Humongous
由于會回收Humongous,所以O(shè)ld的內(nèi)存空間會有減少偏灿,但并不是回收了Old對象
調(diào)整eden與old的占比-
MixedGC
每當(dāng)YoungGC后會根據(jù)JVM參數(shù)(IHOP等)判斷當(dāng)前是否需要開始進行MixedGCMixedGC主要可以分為兩個階段:
1丹诀、全局并發(fā)標(biāo)記(global concurrent marking)全局并發(fā)標(biāo)記又可以進一步細分成下面幾個步驟:
- 初始標(biāo)記(initial mark,STW)翁垂。它標(biāo)記了從GC Root開始直接可達的對象忿墅。初始標(biāo)記階段借用young GC的暫停,因而沒有額外的沮峡、單獨的暫停階段疚脐。
- 并發(fā)標(biāo)記(Concurrent Marking)。這個階段從GC Root開始對heap中的對象標(biāo)記邢疙,標(biāo)記線程與應(yīng)用程序線程并行執(zhí)行棍弄,并且收集各個Region的存活對象信息望薄。過程中還會掃描上文中提到的SATB write barrier所記錄下的引用。
- 最終標(biāo)記(Remark呼畸,STW)痕支。標(biāo)記那些在并發(fā)標(biāo)記階段發(fā)生變化的對象,將被回收蛮原。
- 清除垃圾(Cleanup卧须,部分STW)。這個階段如果發(fā)現(xiàn)完全沒有活對象的region就會將其整體回收到可分配region列表中儒陨。 清除空Region花嘶。
2、拷貝存活對象(Evacuation)
Evacuation階段是全暫停的蹦漠。它負責(zé)把一部分region里的活對象拷貝到空region里去(并行拷貝)椭员,然后回收原本的region的空間。Evacuation階段可以自由選擇任意多個region來獨立收集構(gòu)成收集集合(collection set笛园,簡稱CSet)隘击,CSet集合中Region的選定依賴于上文中提到的停頓預(yù)測模型,該階段并不evacuate所有有活對象的region研铆,只選擇收益高的少量region來evacuate埋同,這種暫停的開銷就可以(在一定范圍內(nèi))可控
錯誤的設(shè)置將會導(dǎo)致無法按期望的進行MixedGC,從而導(dǎo)致FullGC的出現(xiàn)
注意IHOP棵红、G1MaxNewSizePercent莺禁、G1NewSizePercent的關(guān)系
eden的占比要小于1-IHOP才能觸發(fā)MixedGC
(G1NewSizePercent ~ G1MaxNewSizePercent) < 1 - IHOP
已知1
mixedGC觸發(fā)條件:
current heap / total heap > IHOP
(current eden + current old) / total heap > IHOP
mixedGC前總是會觸發(fā)YoungGC:
current eden = 0
綜上滿足該條件時會觸發(fā)mixedGC:
current old / total heap > IHOP
已知2
年老代 = 年老代占比 * 總堆
total old = (1 - total eden percent) * total heap
假設(shè)期望年老代使用占比達到 A 時觸發(fā)mixedGC,則
current old = total old * A
將 已知2 代入 假設(shè) 得
current old = (1 - total eden percent) * total heap * A
再代入 已知1 得
(1 - total eden percent) * total heap * A / total heap > IHOP
簡化得
IHOP < (1 - total eden percent) * A
total eden percent 取值范圍: G1NewSizePercent ~ G1MaxNewSizePercent
為保證能正常mixedGC窄赋,total eden percent 取 G1MaxNewSizePercent
最終
IHOP < (1 - G1MaxNewSizePercent) * A
GC日志
-Xloggc:./tmp/gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
-XX:+PrintGC 輸出GC日志
-XX:+PrintGCDetails 輸出GC的詳細日志
-XX:+PrintGCTimeStamps 輸出GC的時間戳(以基準(zhǔn)時間的形式)
-XX:+PrintGCDateStamps 輸出GC的時間戳(以日期的形式哟冬,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在進行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的輸出路徑
%t
后綴格式生成的時間戳格式為 YYYY-MM-DD_HH-MM-SS
。因此忆绰,生成的日志文件名看起來像這樣 gc-2019-01-29_20-41-47.log
浩峡。