之前對(duì)垃圾回收的過(guò)程有了解蒋纬,但是還是比較模糊只局限于零碎的知識(shí)點(diǎn)泊愧,整個(gè)流程沒(méi)有串起來(lái)村视,今天有空詳細(xì)了解了一下整個(gè)過(guò)程官套,在此記錄一下。
回收目標(biāo)
- 主要是堆內(nèi)存垃圾回收
- 其次也包含方法區(qū)(1.8之后也叫源空間meta)垃圾回收
下面主要介紹堆內(nèi)存的收集
堆內(nèi)存的劃分
盜取一張圖
image.png
- 老年代:用來(lái)存儲(chǔ)多次經(jīng)歷過(guò)Minor GC后仍然存活的對(duì)象(包括達(dá)到指定年齡代的對(duì)象以及Monior GC后無(wú)法放入suvivor區(qū)的對(duì)象蚁孔,無(wú)法放入的部分才會(huì)放入老年代)
- 新生代:用來(lái)存儲(chǔ)程序剛剛分配的對(duì)象奶赔,以及未達(dá)到指定年齡代的對(duì)象
新生代各個(gè)分區(qū)的含義
- eden:程序運(yùn)行新產(chǎn)生的對(duì)象首先會(huì)進(jìn)入eden區(qū)
- survivor:survivor有兩部分,可以稱為 s1, s2 杠氢,其中一塊用來(lái)存儲(chǔ)MinorGC后的數(shù)據(jù)站刑,比如開(kāi)始是Eden+s1滿了之后觸發(fā)MinorGC,然后把存活的對(duì)象移入s2區(qū)鼻百,然后程序再往eden+s2區(qū)放入新對(duì)象绞旅,觸發(fā)MinorGC后把存活的對(duì)象放入s1,依次循環(huán)
垃圾回收有哪些
- MinorGC: 回收新生代的垃圾温艇,不會(huì)暫停用戶線程
- FullGC:回收整個(gè)堆的垃圾因悲,既包含老年代又包含新生代,會(huì)暫停用戶線程
- Major GC:回收老年代中的垃圾勺爱,常用的如CMS垃圾回收器晃琳,當(dāng)老年代的空間達(dá)到設(shè)定的閾值時(shí)(-XX:CMSInitiatingOccupancyFraction與-XX:+UseCMSInitiatingOccupancyOnly參數(shù)決定的),垃圾回收器會(huì)收集老年代中的垃圾,避免產(chǎn)生FullGC
從產(chǎn)生垃圾到垃圾回收產(chǎn)生的流程
- 程序運(yùn)行產(chǎn)生對(duì)象存放到eden與s1中卫旱,當(dāng)新創(chuàng)建的對(duì)象無(wú)法在eden+s1中找到空間則出發(fā)MinorGC
- 如果MinorGC之后存活的對(duì)象小于s2的空間人灼,則放入s2同時(shí)存活對(duì)象的年齡代+1,下次是回收eden+s2顾翼,然后將存活對(duì)象放入到s1
- 重復(fù)步驟2投放,如果在某次回收中存活的對(duì)象的年齡代 > MaxTenuringThreshold設(shè)置的值,這部分對(duì)象直接進(jìn)入老年代暴构,剩下的進(jìn)入s1或s2中的一個(gè)
- 隨著運(yùn)行跪呈,突然某一次MinorGC后存活的對(duì)象很多段磨,多到整個(gè)s1或者s2區(qū)放不下取逾,這時(shí)候會(huì)盡量往s1或s2中存儲(chǔ),存不下的進(jìn)入到老年代苹支,但是進(jìn)入老年代前會(huì)進(jìn)行一系列條件判斷砾隅,如果老年代可用的連續(xù)空間大于那些需要進(jìn)入到老年代,則直接進(jìn)入债蜜,如果不大于晴埂,那么就需要有以下的處理
- 在JDK 6 Update 24之后,JVM直接進(jìn)行一次FullGC寻定,HandlePromotionFailure參數(shù)沒(méi)有意義了
- 在JDK 6 Update 24之前儒洛,如果HandlePromotionFailure 為true,JVM會(huì)再次嘗試進(jìn)行一次MinorGC狼速,但是嘗試是有條件的琅锻,條件就是老年代的連續(xù)空間需要大于歷次MinorGC晉升到老年對(duì)象的平均值,如果小于JVM就會(huì)放棄嘗試直接進(jìn)行FullGC向胡。如果JVM嘗試后還是無(wú)法將多于的對(duì)象放入老年代恼蓬,那么JVM就會(huì)進(jìn)行FullGC;如果HandlePromotionFailure為false僵芹,JVM則直接進(jìn)行FullGC
據(jù)說(shuō)在JDK 6 Update 24前后的變化是因?yàn)镴VM能夠更為智能的處理老年代晉升失敗這種情況了
- 隨著老年代的空間不斷的減少处硬,當(dāng)達(dá)到某個(gè)閾值時(shí),負(fù)責(zé)老年代的垃圾回收器就會(huì)進(jìn)行垃圾回收拇派,比如CMS荷辕,來(lái)降低老年代中的內(nèi)存使用,盡量避免因?yàn)闀x升老年代失敗導(dǎo)致的FullGC件豌。
- 以CMS垃圾回收器為例桐腌,CMS在初始標(biāo)記與重新標(biāo)記時(shí)是暫停所有線程的,但是在并發(fā)標(biāo)記與并發(fā)清除時(shí)是與應(yīng)用程序線程一起執(zhí)行的苟径,意味著在并發(fā)清除的過(guò)程中也會(huì)產(chǎn)生對(duì)象案站,隨之產(chǎn)生MinorGC。因此如果在并發(fā)清除階段,如果通過(guò)MinorGC進(jìn)入老年代的對(duì)象大于老年代清理的速度蟆盐,這是就會(huì)產(chǎn)生concurrent mode failure承边,意味著某次MinorGC后需要進(jìn)入到老年代的對(duì)象比老年代最大的可用連續(xù)空間要多,無(wú)法放入老年代石挂,此時(shí)JVM就會(huì)觸發(fā)一次FullGC
以上是從產(chǎn)生對(duì)象到垃圾回收的整個(gè)過(guò)程博助,此過(guò)程沒(méi)有詳細(xì)介紹細(xì)節(jié)中的概念只是注重流程,具體每步驟的涉及的概念以及詳細(xì)過(guò)程并未解決痹愚,可以網(wǎng)站上檢索