深入理解JVM——(三)為什麼JVM新生代需要兩個Survivor區

PAce發表於2019-01-20

經過了JVM區域的學習,我們知道在堆中新生代具有一個Eden區和兩個Survivor區,這裡就有疑問了,為什麼需要Survivor區和為什麼需要兩個Survivor區?帶著疑問我們思考一下。

一、為什麼需要Survivor區?

帶著這個問題,我們假設一下,如果沒有Survivor區,新生代只有Eden區。

當Eden區裝滿後,Minor GC進行垃圾回收,倖存的物件會直接放入老年代,可以想到,要不了多久老年代就會裝滿,便會進行Major GC且連帶Minor GC也就是Full GC,每次Full GC都會消耗大量的時間。也許你會問,執行時間長有什麼問題?頻發的Full GC會消耗大量的時間,會影響程式的執行與響應速度,導致連線超時等等一系列問題。所以,會出現老年代頻發Full GC而嚴重影響效率的問題

那麼,如果不依靠Survivor區,我們應該如何解決老年代頻發Full GC的問題呢?

方案 優點 缺點
增大老年代記憶體空間 更多物件才會填滿老年代,降低Full GC頻率 每次GC消耗更長的時間
減小老年代記憶體空間 Full GC執行時間減少 Full GC頻率增加

由此可見,沒有Survivor區無法從根本解決問題。

結論:Survivor具有預篩選保證,只有物件到一定歲數才會送往老年代,Survivor區可以減少被送到老年代的物件,進而減少Full GC發生。

二、為什麼需要兩個Survivor區?

可以知道,新生代使用複製回收演算法,我們設想一下只有一個Survivor區會發生什麼情況。

當Eden區填滿後,Minor GC進行垃圾回收,倖存的物件會移動到Survivor區,這樣迴圈往復。此時,Survivor區被裝滿了,也會進行Minor GC,將一些物件kill掉,倖存的物件只能儲存在原來的位置,這樣就會出現大量的記憶體碎片(被佔用記憶體不連續)

記憶體碎片化是嚴重影響效能的,可以設想當有一個稍大一點的物件從Eden區存活轉入Survivor區,發現空閒記憶體斷斷續續,沒有他能落腳的地方,就只能直接存到老年代了,如此反覆,老年代會出現我們第一部分的問題。打個比方:我們出去郊遊,一些吃的罐頭,玩的玩具隨便放在包裡,最後發現最主要的摺疊帳篷放不進去了,只好手拿著到處溜達,非常不方便且影響心情。

最後,如果有兩個Survivor區,便可以保證一個為空,另一個是非空且無碎片儲存的

相關文章