前面我們已經(jīng)提到,對(duì)象間可能會(huì)存在跨代引用,因此最直觀的做法便是掃描其它分區(qū)到伊甸區(qū)的所有引用。但不幸的是這么做會(huì)做成分代的做法變得毫無(wú)意義。JVM對(duì)此有它自己的妙招:卡片式標(biāo)記(card-marking)?;镜淖龇ㄊ牵琂VM將伊甸區(qū)中可能存在老生代引用的對(duì)象標(biāo)記為”臟”對(duì)象。關(guān)于這點(diǎn) Nitsan的博客 這里有更進(jìn)一步的介紹。
標(biāo)記完成后,所有存活對(duì)象會(huì)被復(fù)制到其中的一個(gè)存活區(qū)。于是整個(gè)伊甸區(qū)便可認(rèn)為是清空了,又可以重新用來(lái)分配對(duì)象了。這一過程便被稱為”標(biāo)記復(fù)制“:存活對(duì)象先被標(biāo)記,隨后被復(fù)制到存活區(qū)中。
存活區(qū)(Survivor)
緊挨著伊甸區(qū)的是兩個(gè)存活區(qū),分別是from區(qū)和to區(qū)。值得一提的是其中的一個(gè)存活區(qū)始終都是空的。
空的存活區(qū)會(huì)在下一次新生代GC的時(shí)候迎來(lái)它的居民。整個(gè)新生代中的所有存活對(duì)象(包含伊甸區(qū)以及那個(gè)非空的名為from的存活區(qū))都會(huì)被復(fù)制到to區(qū)中。一旦完成之后,對(duì)象便都跑到to區(qū)中而from區(qū)則被清空了。這時(shí)兩者的角色便會(huì)發(fā)生調(diào)轉(zhuǎn)。
存活對(duì)象會(huì)不斷地在兩個(gè)存活區(qū)之間來(lái)回地復(fù)制,直到其中的一些對(duì)象被認(rèn)為是已經(jīng)成熟,“足夠老”了。請(qǐng)記住這點(diǎn),基于分代假設(shè),已經(jīng)存活了一段時(shí)間的對(duì)象,在相當(dāng)長(zhǎng)的一段時(shí)間內(nèi)仍可能繼續(xù)存活。
這些“年老”的對(duì)象會(huì)被提升至老年代空間。出現(xiàn)對(duì)象提升的時(shí)候,這些對(duì)象則不會(huì)再被復(fù)制到另一個(gè)存活區(qū),而是直接復(fù)制到老年代中,它們會(huì)一直待到不再被引用為止。
垃圾回收器會(huì)跟蹤每個(gè)對(duì)象歷經(jīng)的回收次數(shù),來(lái)判斷它們是否已經(jīng)“足夠年老”,可以傳播至老年代中。在一輪GC完成之后,每個(gè)分區(qū)中存活下來(lái)的對(duì)象的計(jì)數(shù)便會(huì)加一。當(dāng)一個(gè)對(duì)象的年齡超過了一個(gè)特定的年老閾值之后,它便會(huì)被提升到老年代中。