1. 程式人生 > 其它 >深入理解新生代為什麼要分兩個Survivor區?

深入理解新生代為什麼要分兩個Survivor區?

為什麼堆要分新生代和老年代呢?

假設一下,如果不分新老代,記憶體就一整塊,垃圾收集器每次都要把那些長期存在的物件,和生命週期很短的物件放在一起回收,一般長生命週期的物件可能跟應用生命週期一致,你基本回收不掉的,比如Spring 框架裡面的Bean管理相關的物件(ApplicationContext),整個應用執行期間都存在,這種一般經過幾次回收最後都放在老年代,但是如果不區分新老代,每次都一起回收,效能消耗很大。

區分新老代之後,老年代放長期存活的物件,新生代就放生命週期短的物件,老年代物件很穩定,新生代回收不影響老年代,回收效率能大大提高。

新生代為什麼不用垃圾清除或者垃圾整理演算法

若是在新生代使用垃圾清除或者垃圾整理演算法,顯然不需要對新生代進行分割槽。

若是採用標記清除演算法:會在新生代產生記憶體碎片,但是新生代是Java 新物件的出生地,記憶體碎片化顯然是我們不想看到的;

若是採用標記整理演算法:雖然標記整理可以解決記憶體碎片化問題,但是考慮到新生代98%的物件都是“朝生夕死”的,物件被回收掉後會產生很多記憶體碎片,我們移動存活物件的時候需要耗費大量的時間,遠不如直接把這2%物件放到另一個地方採用複製演算法更加高效。

為什麼新生代還要分Eden、From、To區域呢?

前面的分析我們已經得出結論:新生代採用複製演算法更加高效。

如果沒有Survivor區(From + To),Minor GC(新生代回收)過程中,存活的物件直接被送到老年代,這樣的話老年代很快被填滿,觸發Major GC(因為Major GC一般伴隨著Minor GC,也可以看做觸發了Full GC),Full GC頻繁會影響程式的執行和響應速度。

為什麼要設定兩個Survivor區呢?From 和 To

前面的分析我們已經得出結論:新生代採用複製演算法更加高效,且需要對新生代進行分割槽。

主要還是效率問題,假設將新生代分為Eden和Survivor兩個區域,顯然對Eden區採用複製演算法,對Survivor區採用標記整理演算法,這樣又回到在新生代使用複製演算法效率比標記整理效率高的分析。所以需要通過將Survivor區分為From 和 To區解決。