堆內存劃分(新生代、老年代)

在 Java 中,堆被劃分成兩個不同的區域:新生代 ( Young )老年代 ( Old )。新生代 ( Young ) 又被劃分爲三個區域:EdenFrom SurvivorTo Survivor

這樣劃分的目的是爲了使 JVM 能夠更好的管理堆內存中的對象,包括內存的分配以及回收。

堆的內存模型大致如下圖所示:

 

從圖中可以看出: 堆大小 = 新生代 + 老年代

默認情況下:

新生代 ( Young ) 與老年代 ( Old ) 的比例的值爲 1:2

Eden : from : to = 8 : 1 : 1

JVM 每次只會使用 Eden 和其中的一塊 Survivor 區域來爲對象服務,所以無論什麼時候,總是有一塊 Survivor 區域是空閒着的。

因此,新生代實際可用的內存空間爲 9/10 ( 即90% )的新生代空間。

Java 中的堆也是 GC 收集垃圾的主要區域。GC 分爲兩種:Minor GC、Full GC ( 或稱爲 Major GC )。

 

Minor GC

Minor GC 是發生在新生代中的垃圾收集動作,所採用的是複製算法

新生代幾乎是所有 Java 對象出生的地方,即 Java 對象申請的內存以及存放都是在這個地方。Java 中的大部分對象通常不需長久存活,具有朝生夕滅的性質。

當一個對象被判定爲 “死亡” 的時候,GC 就有責任來回收掉這部分對象的內存空間。新生代是 GC 收集垃圾的頻繁區域。

回收過程如下:

  當對象在 Eden ( 包括一個 Survivor 區域,這裏假設是 from 區域 ) 出生後,在經過一次 Minor GC 後,如果對象還存活,並且能夠被另外一塊 Survivor 區域所容納(上面已經假設爲 from 區域,這裏應爲 to 區域,即 to 區域有足夠的內存空間來存儲 Eden 和 from 區域中存活的對象 ),則使用複製算法將這些仍然還存活的對象複製到另外一塊 Survivor 區域 ( 即 to 區域 ) 中,然後清理所使用過的 Eden 以及 Survivor 區域 ( 即 from 區域 ),並且將這些對象的年齡設置爲1,以後對象在 Survivor 區每熬過一次 Minor GC,就將對象的年齡 + 1,當對象的年齡達到某個值時 ( 默認是最大 15 歲,可以通過參數 -XX:MaxTenuringThreshold 來設定 ),這些對象就會成爲老年代。

但這也不是一定的,對於一些較大的對象 ( 即需要分配一塊較大的連續內存空間 )或者Suvivor區已滿,則是直接進入到老年代。

 

Full GC

Full GC 是發生在老年代的垃圾收集動作,通常也會伴隨着新生代的垃圾回收,所採用的是標記-整理算法

現實的生活中,老年代的人通常會比新生代的人 “早死”。堆內存中的老年代(Old)不同於這個,老年代裏面的對象幾乎個個都是在 Survivor 區域中熬過來的,它們是不會那麼容易就 “死掉” 了的。因此,Full GC 發生的次數不會有 Minor GC 那麼頻繁,並且做一次 Full GC 要比進行一次 Minor GC 的時間更長,一般是Minor GC的 10倍以上。

 

 

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