1. 程式人生 > >新生代Eden區、兩個Survivor區及老年代的關係

新生代Eden區、兩個Survivor區及老年代的關係

偶然想起JVM年輕代中Eden區和兩個Survivor的比例,就想根據自己的理解和大家探討一下為什麼要配成8 :1 :1的比例。

一、JVM堆分代

1、JVM堆被分為了年輕代和老年代。年輕代的GC過程稱為Yong GC,速度快較頻繁。老年代的GC過程稱為Full GC,速度較慢應該儘量避免。

2、物件被建立後,除了少部分大物件會在老年代分配記憶體外,大部分的物件首先都是在年輕代進行記憶體分配,而且大部分的物件都是“朝生夕死”,很快就會被年輕代的Yong GC回收掉。

3、老年代的記憶體空間一般會比年輕代的記憶體空間大,能存放的物件多,老年代的空間不足後會進行Full GC操作,比Yong GC耗時,所以應儘量避免頻繁的Full GC操作。

二、年輕代的分割槽

1、年輕代中分為一個Eden區和兩個Surviver區,比例為8:1:1,兩個Surviver區分別稱為“From”區和“To”區。物件在Eden區建立,經過一次Yong GC後,還存活的物件將會被複制到Surviver區的“From”區,此時“To”區是空的。到了下一次GC的時候,Eden區還存活的物件會直接移動到Surviver區的“To”區,而“Form”區的物件有兩個去處,“From”區的物件會根據經過的GC次數計算年齡,如果年齡到達了閾值(預設18),則會被移動到老年代中,否則就複製到“To”區,此時“From”區變成了空的,然後“From”區和“To”區進行角色互換,到下一次進行GC時,還是有一塊空的“To”區,用來存放從eden區和“From”區移動過來的物件。

2、那這種分割槽有什麼好處呢?

a、在年輕代新增Surviver區,有利於減輕老年代的負擔,儘可能的讓大部分物件在年輕代通過較高效的Yong GC回收掉,不至於老年代裡存放的物件過多導致記憶體不足而進行頻繁的Full GC操作。

b、這種分割槽有利於減少記憶體碎片的產生。

首先我們來看看,如果年輕代只分為Eden區和Surviver區兩個區域並且比例是8:2的時候,記憶體的回收和分配情況會怎麼樣。第一次Yong GC後,Eden區還存活的物件移動到Surviver區,Surviver區還存活的物件保留在Surviver區,而這些物件的記憶體是不連續的,Surviver區裡就會產生很多記憶體碎片,這就會導致有些大物件要移動到Surviver區的時候,沒有足夠的連續記憶體進行分配,而不得不移動到老年代中,增加老年代的負擔,降低效率。

然後我們看看Eden區和Surviver區的比例是8:1:1時會有什麼樣的效果。第一次Yong GC後,Eden區還存活的物件移動到Surviver區的“To”區,“From”區還存活的物件也移動到“To”區,這樣就等於“From”區完全是空的了,而“To”區也不會有記憶體碎片產生,等到第二次Yong GC時,“From”區和“To”區角色互換,很好的解決了記憶體碎片的問題。

如下圖所示:

有人要說為什麼一定是8:1:1的比例呢,這大概是前輩們實踐出來的最佳比例吧~~