JVM垃圾回收算法和垃圾回收器

一、垃圾回收算法
1、標記複製算法
會把內存分爲相同的2個部分,每次回收,會把存活的對象移動到另一邊,回收當前使用的空間。分配的內存被分成2份,實際使用空間變成正常的一半。但是不會出現垃圾碎片。

2、標記清除算法
標記存活的對象,把未標記的回收。回收後內存不是連續的,會產生大量的不連續的碎片,標記對象的時候效率低。

3、標記整理(壓縮)算法
會把存活的對象移動到一起,清除邊間外的垃圾對象,效率低

二、垃圾回收器
1、Serial和SerialOld
Serial是新生代,SerialOld是老年代的回收期,串行化執行,最簡單的單線程的收集器,會STW。
CMS收集器如果空間不夠無法進行FULL-GC,就會用SerialOld進行回收。
Serial使用標記複製,SerialOld使用標記整理算法

2、Parallel Scavenge收集器 Parallel Old
使用多線程,其他的和Serial相同,關心吞吐量,會自動調整參數設置吞吐量的大小,停頓的時間,提供最優的吞吐量。JDK8默認的收集器
新生代採用複製算法,老年代使用標記整理算法。

3、parNew收集器
使用多線程,其他的和Serial相同。使用複製算法
新生代的收集器,可以搭配CMS收集器使用,

4、CMS收集器
爲了提高用戶的體驗,提供最短的STW,併發收集,可以讓垃圾回收線程和用戶線程同時使用,標記清除算法,默認情況下是老年代內存達到92%會執行FullGC。
分爲以下階段:
(1)初始標記:會STW,但是速度非常快,標記GCROOT能引用的對象,可以用-XX:+CMSParallellnitialMarkEnabled參數開啓多線程執行。
(2)併發標記:根據GCROOT遍歷所有對象,過程比較慢,不會STW,會和用戶線程一起執行。
(3)重新標記:因爲併發標記中垃圾回收線程會和用戶線程一同執行,可能會出現,被標記爲垃圾對象的現在不是垃圾對象了會對產生變動的重新進行標記。會STW,比初始標記時間長,併發標記時間短。可以用 -XX:+CMSParallelRemarkEnabled 參數開啓多線程重新標記。(存活的對象現在是垃圾對象,可達變不可達,是不會被重新標記的,這個是浮動垃圾)
(4)併發清理:和用戶線程一同執行,對未標記的對象清理,這個階段如果有新添加的對象,會被標記爲黑色。
(5)併發重置:重置本次標記的對象,與用戶線程一同運行。

優點: 併發執行,低停頓,用戶體驗較好
缺點:

會產生浮動垃圾只能等待下一次回收
佔用CPU資源
標記清除會產生空間碎片,可以通過開啓參數,做完發FullGC自動整理碎片( -XX:+UseCMSCompactAtFullCollection),可以通過參數設置多少次FullGC整理一次內存碎片( -XX:CMSFullGCsBeforeCompaction)
在FullGC執行前,可以先進行一次YGC來減少內存對象的引用,加快CMS在FullGC時標記的速度(-XX:+CMSScavengeBeforeRemark)

 

 


5、G1收集器
G1收集器把java的堆分爲多個大小相等的區域Region,最多可以有2048個Region。一個Region = 堆容量/2048。適合大內存。

年輕代(eden,survivor),佔總容量的5%,但是在JVM運行的時候,會不斷地給年輕代調整Region最多佔60%可以通過參數調整-XX:G1MaxNewSizePercent。
老年代:
Humongous區:專門用來存儲大對象,如果這個對象超過Region的50%就是一個大對象
在進行GC的時候年輕代、老年代、大對象區都會被回收。
(1)初始標記:會STW,記錄GCROOT可以引用的對象,速度快
(2)併發標記:根據GCROOT遍歷所有對象,過程比較慢,不會STW,會和用戶線程一起執行。
(3)最終標記:和CMS的重新標記相同。
(4)篩選回收:根據設置的GC停頓時間(-XX:MaxGCPauseMillis)來設置回收計劃,會對各個Region的進行回收的時間計算,優先選擇回收價值高的Region來進行回收。默認的回收次數是8次,可以通過(-XX:G1MixedGCCountTarget)控制回收幾次。會STW。
年輕代和老年代都是使用的複製回收算法,把一個Region複製到另一個Region中,不會出現空間碎片

YGC:YCG並不是Eden區滿了就去回收,會先計算回收Eden需要多長時間,如果回收時間小於設置的回收時間,就繼續給Eden分配Region,直到下一次滿了在判斷回收時間,如果接近設置的回收時間,就觸發YGC.
MixedGC:老年代的佔有率達到回收的默認45%,就會執行MixedGC,回收所有的年輕代、部分老年代和大對象,在這個過程中,如果剩下的空Region放不下存活的對象,就會觸發FGC。
FGC:停止系統程序,採用單線程進行標記、清理、壓縮,這個過程非常耗時。

 

 

三、三色標記算法
1、黑色
代表這個對象所有的引用都被掃描完成。

2、灰色
這個對象所有的引用可能還有至少1個對象引用沒有被掃描到

3、白色
還沒有掃描的會被標記爲白色,如果在GC併發標記完成後,還是白色,就代表這個對象不可達,是個垃圾對象

在併發標記的過程中,用戶線程和標記線程是同時運行的,這個時候就會出現已經是垃圾對象的被重新引用,但是它已經被標記爲白色,或者某個對象由存活對象變成垃圾對象,對象的引用發生了改變,這個時候就會出現多標或者漏標

4、漏標
漏標會把引用的對象當成垃圾回收掉,可以用增量更新或者原始快照實現

(1)增量更新-CMS
黑色對象指向白色對象的引用時,就把這個新插入的引用記錄下來,等併發掃描結束後,在把這些記錄過引用關係的跟節點重新掃描。

(2)原始快照(SATB)-G1
灰色對象要刪除指向白色對象的引用,把這個刪除的引用記錄下來,在併發掃描結束後,在把這個灰色的對象重新掃描,這樣就能掃描到這個對象,然後把這個白色的對象標記爲黑色,等待下一次GC,這個白色的對象有可能是浮動垃圾。

(3)增量更新和原始快照都需要和寫屏障來實現
寫前操作,寫後操作
寫屏障實現增量更新: 把新的應用對象記錄下來
寫屏障實現SATB: 把刪除的引用存放到隊列中

5、多標-浮動垃圾
執行併發標記的時候有些被掃描過得存活對象,已經銷燬,它已經被標記爲黑色,這些對象就是浮動垃圾,還有就是併發清理開始後產生的對象會被當成黑色,但是他有可能是垃圾對象,這些都是浮動垃圾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章