1、Young為年輕代出發(fā)的垃圾回收器。
2、Old為老觸發(fā)的垃圾回收器。
3、連線代表的是垃圾回收器的組合。CMS 和Serial Old連線代表CMS一旦不行了,Serial Old上場。
首先了解一個概念:STW
1、什么是STW?
STW是Stop-The-World縮寫: 是在垃圾回收算法執(zhí)?過程當(dāng)中,將JVM內(nèi)存凍結(jié)丶應(yīng)用程序停頓的?種狀態(tài)。
1、在STW 狀態(tài)下,JAVA的所有線程都是停?執(zhí)?的 -> GC線程除外
2、一旦Stop-the-world發(fā)生,除了GC所需的線程外,其他線程都將停止工作,中斷了的線程直到GC任務(wù)結(jié)束才繼續(xù)它們的任務(wù)。
3、STW是不可避免的,垃圾回收算法執(zhí)?一定會出現(xiàn)STW,我們要做的只是減少停頓的時間
GC各種算法優(yōu)化的重點,就是減少STW(暫停),同時這也是JVM調(diào)優(yōu)的重點。
2、什么時候進(jìn)入STW狀態(tài)?
可達(dá)性分析算法中枚舉根節(jié)點(GC Roots)會導(dǎo)致所有Java執(zhí)行線程停頓,進(jìn)入STW狀態(tài)
3、為什么一定要STW停頓的原因?
1、分析工作必須在一個能確保一致性的快照中進(jìn)行
2、一致性指整個分析期間整個執(zhí)行系統(tǒng)看起來像被凍結(jié)在某個時間點上
3、如果出現(xiàn)分析過程中對象引用關(guān)系還在不斷變化,則分析結(jié)果的準(zhǔn)確性無法保證
4、被STW中斷的應(yīng)用程序線程會在完成GC之后恢復(fù),頻繁的中斷會讓用戶感覺卡頓
5、所以我們要減少STW的發(fā)生,也就相當(dāng)于要想辦法降低GC垃圾回收的頻率
6、STW狀態(tài)和采用哪款GC收集器無關(guān),所有的GC收集器都有這個狀態(tài),因為要保證一致性。
7、但是好的GC收集器可以減少停頓的時間、減少STW(暫停)和降低GC垃圾回收的頻率是調(diào)優(yōu)的重點
如果系統(tǒng)卡頓很明顯,大概率就是頻繁執(zhí)行GC垃圾回收,頻繁進(jìn)入STW狀態(tài)產(chǎn)生停頓的緣故
記住,目前所有垃圾收集器都會進(jìn)入STW機(jī)制
一、Serial收集器(單線程收集器,新時代,采用復(fù)制算法)
這個收集器是一個單線程的收集器,但它的“單線程”的意義并不僅僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工作,會進(jìn)行SWT,停掉除了GC線程之外的所有的工作線程,直到它收集結(jié)束,才繼續(xù)執(zhí)行其它的工作線程。
例:當(dāng)一個小孩在房間玩,亂丟垃圾,這時他媽媽進(jìn)來收拾垃圾了,會把小孩抱到一邊,不讓他玩先,等收拾好垃圾,在讓他玩。
二、Serial Old收集器(單線程收集器,老年代,采用標(biāo)記整理算法)
Serial Old是Serial收集器的老年代版本,它同樣是一個單線程收集器。會進(jìn)行SWT,停掉除了GC線程之外的所有的工作線程,直到它收集結(jié)束,才繼續(xù)執(zhí)行其它的工作線程。
三、Parallel Scavenge收集器(多線程收集器,新生代、采用復(fù)制算法)
Parallel Scavenge 收集器也是一款新生代收集器,它同樣是基于標(biāo)記 -復(fù)制算法實現(xiàn)的收集器,是 能夠并行收集的多線程收集器。
Parallel Scavenge收集器的特點是它的關(guān)注點與其他收集器不同。Parallel Scavenge收集器的目標(biāo)則是達(dá)到一個可控制的吞吐量(Throughput)。所謂吞吐量就是處理器用于運行用戶代碼的時間與處理器總消耗時間的比值,即:
舉例說明:
如果虛擬機(jī)完成某個任務(wù),用戶代碼加上垃圾收集總共耗費了 100 分鐘,其中垃圾收集花掉 1 分
鐘,那吞吐量就是 99% 。
Parallel Scavenge收集器也經(jīng)常被稱作“吞吐量優(yōu)先收集器”。
如果在上線之前沒有做任何JVM調(diào)優(yōu)或設(shè)置話,默認(rèn)的就是Parallel Scavenge + Paraller Old組合垃圾回收器,簡稱PS + PO
四、Paraller Old收集器(多線程收集器,老年代,采用標(biāo)記整理算法)
Parallel Old是Parallel Scavenge收集器的老年代版本
五、ParNew收集器(多線程收集器,新時代,采用標(biāo)記-整理算法)
ParNew說白了和Parallel Scavenge一樣的,區(qū)別組了做了增強,以便能讓它和CMS配合使用。
六、CMS收集器(多線程收集器,老年代,采用標(biāo)記—清除算法)
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標(biāo)的收集器
從名字(包含“Mark Sweep”)上就可以看出,CMS收集器是基于“標(biāo)記—清除”算法實現(xiàn)的,它的運作過程相對于前面幾種收集器來說更復(fù)雜一些,整個過程分為4個步驟,包括:
初始標(biāo)記(CMS initial mark)
并發(fā)標(biāo)記(CMS concurrent mark)
重新標(biāo)記(CMS remark)
并發(fā)清除(CMS concurrent sweep)
1、初始標(biāo)記(觸發(fā)STW):初始標(biāo)記僅僅只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快。
2、并發(fā)標(biāo)記(不觸發(fā)STW):并發(fā)標(biāo)記階段就是從GC Roots的直接關(guān)聯(lián)對象開始遍歷整個對象圖的過程, 這個過程耗時較長但是不需要停頓用戶線程, 可以與垃圾收集線程一起并發(fā)運行。因為用戶程序繼續(xù)運行,可能會有導(dǎo)致已經(jīng)標(biāo)記過的對象狀態(tài)發(fā)生改變。所以要進(jìn)行一次重新標(biāo)記。
3、重新標(biāo)記(觸發(fā)STW):重新標(biāo)記階段就是為了修正并發(fā)標(biāo)記期間因為用戶程序繼續(xù)運行而導(dǎo)致標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記記錄,就是并發(fā)標(biāo)記過程中產(chǎn)生的新垃圾,進(jìn)行標(biāo)記,或者到重新標(biāo)記這一階段,又要用到并發(fā)標(biāo)記已經(jīng)標(biāo)記的垃圾,取消垃圾標(biāo)記。 這個階段的停頓時間一般會比初始標(biāo)記階段的時間稍長,遠(yuǎn)遠(yuǎn)比并發(fā)標(biāo)記階段時間短。
4、并發(fā)清理(不觸發(fā)STW) :開啟用戶線程,同時GC線程開始對未標(biāo)記的區(qū)域做清掃。這個階段如果有新增對象會被標(biāo)記為黑色不做任何處理,等下次重新觸發(fā)在進(jìn)行處理。
CMS問題:
七、G1(多線程收集器,標(biāo)記-整理)
1、G1 垃圾收集器的內(nèi)存模型
G1 收集器不采用傳統(tǒng)的新生代和老年代物理隔離的布局方式,僅在邏輯上劃分新生代和老年代,將整個堆內(nèi)存劃分為2048個大小相等的獨立內(nèi)存塊Region,每個Region是邏輯連續(xù)的一段內(nèi)存,具體大小根據(jù)堆的實際大小而定,整體被控制在 1M - 32M 之間,且為2的N次冪(1M、2M、4M、8M、16M和32M),并使用不同的Region來表示新生代和老年代,G1不再要求相同類型的 Region 在物理內(nèi)存上相鄰,而是通過Region的動態(tài)分配方式實現(xiàn)邏輯上的連續(xù)。
G1收集器通過跟蹤Region中的垃圾堆積情況,每次根據(jù)設(shè)置的垃圾回收時間,回收優(yōu)先級最高的區(qū)域,避免整個新生代或整個老年代的垃圾回收,使得stop the world的時間更短、更可控,同時在有限的時間內(nèi)可以獲得最高的回收效率。
通過區(qū)域劃分和優(yōu)先級區(qū)域回收機(jī)制,確保G1收集器可以在有限時間獲得最高的垃圾收集效率。
2、分區(qū)Region:
G1 垃圾收集器將堆內(nèi)存劃分為若干個 Region,每個 Region 分區(qū)只能是一種角色,Eden區(qū)、S區(qū)、老年代區(qū)的其中一個,空白區(qū)域代表的是未分配的內(nèi)存,最后還有個特殊的區(qū)域H(Humongous),專門用于存放巨型對象,如果一個對象的大小超過Region容量的50%以上,G1 就認(rèn)為這是個巨型對象。在其他垃圾收集器中,這些巨型對象默認(rèn)會被分配在老年代,但如果它是一個短期存活的巨型對象,放入老年代就會對垃圾收集器造成負(fù)面影響,觸發(fā)老年代頻繁GC。
為了解決這個問題,G1劃分了一個H區(qū)專門存放巨型對象,如果一個H區(qū)裝不下巨型對象,那么G1會尋找連續(xù)的H分區(qū)來存儲,如果尋找不到連續(xù)的H區(qū)的話,就不得不啟動 Full GC 了。
3、card table
卡表是 CMS 的解決方案。
官方解釋:A kind of remembered set that records where oops have changed in a generation.
問題: 新生代回收為什么可以不全表掃描標(biāo)記?
答案: 只標(biāo)記在新生代區(qū)的根引用+ cardTable上的標(biāo)記。
作用:采用空間換時間,不需要掃描整個Heap空間,降低MonitorGC耗時。
4、Remember Set:
在串行和并行收集器中,GC時是通過整堆掃描來確定對象是否處于可達(dá)路徑中。然而G1為了避免STW式的整堆掃描,為每個分區(qū)各自分配了一個 RSet(Remembered Set),它內(nèi)部類似于一個反向指針,記錄了其它 Region 對當(dāng)前 Region 的引用情況,這樣就帶來一個極大的好處:回收某個Region時,不需要執(zhí)行全堆掃描,只需掃描它的 RSet 就可以找到外部引用,來確定引用本分區(qū)內(nèi)的對象是否存活,進(jìn)而確定本分區(qū)內(nèi)的對象存活情況,而這些引用就是 initial mark 的根之一。
事實上,并非所有的引用都需要記錄在RSet中,如果引用源是本分區(qū)的對象,那么就不需要記錄在 RSet 中;同時 G1 每次 GC 時,所有的新生代都會被掃描,因此引用源是年輕代的對象,也不需要在RSet中記錄;所以最終只需要記錄老年代到新生代之間的引用即可。
5、Mixed GC:
年輕代不斷進(jìn)行垃圾回收活動后,為了避免老年代的空間被耗盡。當(dāng)占用空間超過整堆比 IHOP 閾值 -XX:InitiatingHeapOccupancyPercent(默認(rèn)45%)時,G1就會啟動一次混合垃圾回收Mixed GC,Mixed GC不僅進(jìn)行正常的新生代垃圾收集,同時也回收部分后臺掃描線程標(biāo)記的老年代分區(qū)。Mixed GC步驟主要分為兩步:
這里需要特別注意的是 Mixed GC 并不是 Full GC,只有當(dāng) Mixed GC 來不及回收old region,也就說在需要分配老年代的對象時,但發(fā)現(xiàn)沒有足夠的空間,這個時候就會觸發(fā)一次 Full GC
6、并發(fā)標(biāo)記算法
三色標(biāo)記算法:
三色標(biāo)記算法是并發(fā)收集階段的重要算法,它是描述追蹤式回收器的一種有用的方法,利用它可以推演回收器的正確性。 首先,我們將對象分成三種類型的。
三色標(biāo)記算法的正常流程:
(1)根對象被置為黑色,子對象被置為灰色:
(2)繼續(xù)由灰色遍歷,將已掃描了子對象的對象置為黑色。
(3)遍歷了所有可達(dá)的對象后,所有可達(dá)的對象都變成了黑色。不可達(dá)的對象即為白色,需要被清理。
漏標(biāo):
在并發(fā)標(biāo)記過程中,黑色對象指向了白色對象,以此同時灰色對象取消了對白色對象的引用,就會造成漏標(biāo),因為A是黑色對象,不需要在掃描了,B又取消了對D的引用,從而產(chǎn)生漏標(biāo)文章來源:http://www.zghlxwxcb.cn/news/detail-719042.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-719042.html
八、GC常用的參數(shù)
GC常用參數(shù)
- -Xmn -Xms -Xmx -Xss
年輕代 最小堆 最大堆 棧空間 - -XX:+UseTLAB
使用TLAB,默認(rèn)打開 - -XX:+PrintTLAB
打印TLAB的使用情況 - -XX:TLABSize
設(shè)置TLAB大小 - -XX:+DisableExplictGC
System.gc()不管用 ,F(xiàn)GC - -XX:+PrintGC
- -XX:+PrintGCDetails
- -XX:+PrintHeapAtGC
- -XX:+PrintGCTimeStamps
- -XX:+PrintGCApplicationConcurrentTime (低)
打印應(yīng)用程序時間 - -XX:+PrintGCApplicationStoppedTime (低)
打印暫停時長 - -XX:+PrintReferenceGC (重要性低)
記錄回收了多少種不同引用類型的引用 - -verbose:class
類加載詳細(xì)過程 - -XX:+PrintVMOptions
- -XX:+PrintFlagsFinal -XX:+PrintFlagsInitial
必須會用 - -Xloggc:opt/log/gc.log
- -XX:MaxTenuringThreshold
升代年齡,最大值15 - 鎖自旋次數(shù) -XX:PreBlockSpin 熱點代碼檢測參數(shù)-XX:CompileThreshold 逃逸分析 標(biāo)量替換 …
這些不建議設(shè)置
Parallel常用參數(shù)
- -XX:SurvivorRatio
- -XX:PreTenureSizeThreshold
大對象到底多大 - -XX:MaxTenuringThreshold
- -XX:+ParallelGCThreads
并行收集器的線程數(shù),同樣適用于CMS,一般設(shè)為和CPU核數(shù)相同 - -XX:+UseAdaptiveSizePolicy
自動選擇各區(qū)大小比例
CMS常用參數(shù)
- -XX:+UseConcMarkSweepGC
- -XX:ParallelCMSThreads
CMS線程數(shù)量 - -XX:CMSInitiatingOccupancyFraction
使用多少比例的老年代后開始CMS收集,默認(rèn)是68%(近似值),如果頻繁發(fā)生SerialOld卡頓,應(yīng)該調(diào)小,(頻繁CMS回收) - -XX:+UseCMSCompactAtFullCollection
在FGC時進(jìn)行壓縮 - -XX:CMSFullGCsBeforeCompaction
多少次FGC之后進(jìn)行壓縮 - -XX:+CMSClassUnloadingEnabled
- -XX:CMSInitiatingPermOccupancyFraction
達(dá)到什么比例時進(jìn)行Perm回收 - GCTimeRatio
設(shè)置GC時間占用程序運行時間的百分比 - -XX:MaxGCPauseMillis
停頓時間,是一個建議時間,GC會嘗試用各種手段達(dá)到這個時間,比如減小年輕代
G1常用參數(shù)
- -XX:+UseG1GC
- -XX:MaxGCPauseMillis
建議值,G1會嘗試調(diào)整Young區(qū)的塊數(shù)來達(dá)到這個值 - -XX:GCPauseIntervalMillis
?GC的間隔時間 - -XX:+G1HeapRegionSize
分區(qū)大小,建議逐漸增大該值,1 2 4 8 16 32。
隨著size增加,垃圾的存活時間更長,GC間隔更長,但每次GC的時間也會更長
ZGC做了改進(jìn)(動態(tài)區(qū)塊大小) - G1NewSizePercent
新生代最小比例,默認(rèn)為5% - G1MaxNewSizePercent
新生代最大比例,默認(rèn)為60% - GCTimeRatio
GC時間建議比例,G1會根據(jù)這個值調(diào)整堆空間 - ConcGCThreads
線程數(shù)量 - InitiatingHeapOccupancyPercent
啟動G1的堆空間占用比例
到了這里,關(guān)于JVM常見的垃圾回收器(詳細(xì))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!