JVM堆區(qū)新生代為什么有兩個Survivor

JVM內(nèi)存模型中, Heap區(qū)被分為新生代和老年代兩個區(qū)域, 新生代又分為Eden+Survivor1+Survivor2. 新生代收集算法主要使用復(fù)制算法, 老年代收集算法主要使用標(biāo)記-清理或標(biāo)記-整理算法.

堆內(nèi)存劃分

新生代在發(fā)生首次YGC的時候, Eden內(nèi)存活的對象會被復(fù)制到S1.


再發(fā)生YGC的時候, Eden內(nèi)存活的對象和S1內(nèi)存活的對象會被復(fù)制到S2, 同時清除Eden內(nèi)的對象和S1內(nèi)的對象.


再發(fā)生YGC的時候, Eden內(nèi)存活的對象和S2內(nèi)存活的對象會被復(fù)制到S1, 同時清除Eden內(nèi)的對象和S2內(nèi)的對象.


以此往復(fù)循環(huán). 生存次數(shù)超過閾值的對象進入老年代. 可以總結(jié)得出: 每次YGC發(fā)生之后, S1和S2總會有一個是空的, 這樣子的目的是避免內(nèi)存碎片化帶來的空間與性能損失. 請注意筆者畫圖的時候故意畫出間隔很大的不同內(nèi)存區(qū)域, 實際情況中這就是存活對象的內(nèi)存分布.
現(xiàn)在想象一下如果只有一個Survivor區(qū), 那么每次YGC的時候, Eden區(qū)和S區(qū)都會有內(nèi)存碎片, 這是無疑的一點, 此時如果將Eden區(qū)內(nèi)存活的對象直接復(fù)制到S區(qū), 那么內(nèi)存情況將會是如下:
(慘不忍睹...)


隨著一次次的YGC, S區(qū)內(nèi)的內(nèi)存碎片無疑會變得越來越多.內(nèi)存浪費非常嚴(yán)重. 這里有人可能會想: 我們好像也可以在每次YGC的時候, 對S區(qū)內(nèi)的對象進行重排列, 使得S區(qū)內(nèi)的對象一個個緊挨著彼此, 避免內(nèi)存碎片化. 這個想法是可以的, 但是要考慮到Y(jié)GC是JVM垃圾收集中最最最頻繁的活動. 如果每次YGC時都要花費這么多時間去重排列對象, 對象重排列相比直接復(fù)制, 是很耗時的計算. 因此劃分出兩個Survivor區(qū)域, 以空間為代價(每次都有一個S區(qū)為空)換取GC時間, 是很值得的事情. 提升了服務(wù)器響應(yīng)性.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容