JVM初學之堆的內存模型

定義:

堆是JVM運行時內存區域中最大的一個區域,我們平常創建的對象,數組的內存都是在堆上分配的。

堆不僅僅只是一塊大區域,它分爲多個不同作用的區域。

  1. Old區。
  2. Young區。Young區又分爲Eden區和兩個大小相同的Survivor區,這兩個區有的叫s1 和 s2 也有將from 區 和 to區。

在這裏插入圖片描述
解釋:如圖,左邊的是old區,右邊的是Young區。Young區又分爲Eden區和Survivor區,Survivor區又分爲大小相同的s1區和s2區。

Old區(老年代):

  1. old區一般都會存儲着年齡比較大的對象,這裏的年齡不是指存在時間,而是每一次young區的垃圾回收後,沒有被回收掉的對象都會年齡加一,默認經過15次垃圾回收後沒有被回收掉的對象,就會從young區進入到old區。
  2. 某個對象的大小超過某個閾值之後,會直接進入old區。
  3. old區是相對比較穩定的區域。

Young區(年輕代):

Young區分爲兩大塊,一個是Survivor(s1 + s2),一塊是Eden區,
Eden:s1: s2 = 8:1:1 。

Eden區:

正常創建對象分配內存的區域,大多數對象都是“朝生夕死”,就是大多數對象都會被垃圾回收掉。

Survivor區:

  1. Survivor區分爲兩塊s1和s2。
  2. 在同一個時間點上,s1和s2只能有一個區有數據,另一個是空的。

爲什麼要區分出這些不同的區域呢,直接一個堆會怎麼樣:

在這裏插入圖片描述
如上圖所示:藍色的對象時要回收的對象,假如不只有一個堆,而不劃分區間的話,進行一個回收之後,就會導致堆的內存空間不連續,零零散散,導致如果分配大的對象的話,會沒有足夠的連續空間來分配,又回導致gc啓動,最終導致oom。

但是如果僅僅區分old區跟young區的話,也會出現上述問題。

所以就分配除了如上的內存模型劃分。這個模型的好處如下:

  1. 首先一般正常對象創建都會在Eden區分配內存。當Eden區無法爲對象分配足夠內存時,就是觸發Young GC。
  2. Young GC 會把Eden區和其中一個Survivor區(假如s1)的存活對象複製到另一個Survivor區(假如s2),然後把Eden區和s1區的所有對象清除掉。待得下次Young GC就會把s2 和 Eden區的對象複製到s1,然後再清空s2和Eden區。
  3. 以上第二點機制就是就可以保證內存空間連續,不會出現碎片現象,因爲Eden區的數據每次都會被清空。但是會浪費其中一個Survivor區的空間,因爲總有一個Survivor區是空的,用於待定,待複製。
    假如Eden:s1:s2 = 8:1:1的話,就會意味着犧牲10%的Young區內存,換得GC後內存的連續性。
  4. 因爲young區的對象大多數都是朝生夕死的,一般來說8:1:1是較爲合理的,假如是6:2:2的話,就會浪費20%的young區內存,並且Eden區只有60%,這樣會導致較爲頻繁的gc。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章