JVM(六)爲什麼新生代有兩個Survivor分區?

本文會使用排除法的手段,來講解新生代的區域劃分,從而讓讀者能夠更清晰的理解分代回收器的原理,在開始之前我們先來整體認識一下分代收集器。

分代收集器會把內存空間分爲:老生代和新生代兩個區域,而新生代又會分爲:Eden 區和兩個 Survivor區(From Survivor、To Survivor),來看內存空間分佈圖,如下:

分代圖

(圖片來自 fancydeepin)

可以看出 Eden 和 Survivor 分區的默認比例是 8:1:1,這個值可以通過:–XX:SurvivorRatio 設定,默認值: –XX:SurvivorRatio=8。

順便說一下,新生代和老生代默認情況下的內存佔比是 1:2,該值可以通過:-XX:NewRatio 來設定。

爲什麼 Survivor 分區不能是 0 個?

如果 Survivor 是 0 的話,也就是說新生代只有一個 Eden 分區,每次垃圾回收之後,存活的對象都會進入老生代,這樣老生代的內存空間很快就被佔滿了,從而觸發最耗時的 Full GC ,顯然這樣的收集器的效率是我們完全不能接受的。

爲什麼 Survivor 分區不能是 1 個?

如果 Survivor 分區是 1 個的話,假設我們把兩個區域分爲 1:1,那麼任何時候都有一半的內存空間是閒置的,顯然空間利用率太低不是最佳的方案。

但如果設置內存空間的比例是 8:2 ,只是看起來似乎“很好”,假設新生代的內存爲 100 MB( Survivor 大小爲 20 MB ),現在有 70 MB 對象進行垃圾回收之後,剩餘活躍的對象爲 15 MB 進入 Survivor 區,這個時候新生代可用的內存空間只剩了 5 MB,這樣很快又要進行垃圾回收操作,顯然這種垃圾回收器最大的問題就在於,需要頻繁進行垃圾回收。

爲什麼 Survivor 分區是 2 個?

如果 Survivor 分區有 2 個分區,我們就可以把 Eden、From Survivor、To Survivor 分區內存比例設置爲 8:1:1 ,那麼任何時候新生代內存的利用率都 90% ,這樣空間利用率基本是符合預期的。再者就是虛擬機的大部分對象都符合“朝生夕死”的特性,所以每次新對象的產生都在空間佔比比較大的 Eden 區,垃圾回收之後再把存活的對象方法存入 Survivor 區,如果是 Survivor 區存活的對象,那麼“年齡”就 +1 ,當年齡增長到 15 (可通過 -XX:+MaxTenuringThreshold 設定)對象就升級到老生代。

總結

根據上面的分析可以得知,當新生代的 Survivor 分區爲 2 個的時候,不論是空間利用率還是程序運行的效率都是最優的,所以這也是爲什麼 Survivor 分區是 2 個的原因了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章