爲什麼新生代裏面的堆內存要分爲8:1:1呢?

1.引言

看到這個問題,很多同學可能會有點懵B。覺得是虛擬機自己就是這麼分配的,那有那麼多的爲什麼?????

但當你面試的時候,被面試官這麼問到時,難道你也如此答覆別人嗎?如果是的,兄嘚。你可能就得被扣分了!

 

2.原理

GC是統計學測算出當內存使用超過98%以上時,內存就應該被minor gc時回收一次。但是實際應用中,我們不能較真的只給 他們留下2%,換句話說當內存使用達到98%時才GC 就有點晚了,應該是多一些預留10%內存空間,這預留下來的空間我們稱爲S區(有兩個s區  s1 和  s0),S區是用來存儲新生代GC後存活下來的對象,而我們知道新生代GC算法使用的是複製回收算法。

         所以我們實際GC發生是在,新生代內存使用達到90%時開始進行,複製存活的對象到S1區,要知道GC結束後在S1區活下來的對象,需要放回給S0區,也就是對調(對調是指,兩個S區位置互換,意味着再一次minor gc 時的區域  是eden 加,上一次存活的對象放入的S區),既然能對調,其實就是兩個區域一般大。這也是爲什麼會再有個10%的S0區域出來。這樣比例就是8:1:1了!!(80%:s1:s0=80%:10%:10%=8:1:1)這裏的eden區(80%) 和其中的一個  S區(10%) 合起來共佔據90%,GC就是清理的他們,始終保持着其中一個  S  區是空留的,保證GC的時候複製存活的對象有個存儲的地方。

     (注意:如何判斷對象存活可用,可達性分析法來判斷:通過一系列稱爲 GCRoot 對象做起點,從這些節點向下搜索,搜索所走過的路徑稱爲引用鏈,如果一個對象在引用鏈上,就說是可達的,這種對象就是需要存活下來的!!,

作爲GC Roots的對象包括下面幾種:

1.當前虛擬機棧中局部變量表中的引用的對象

2.當前本地方法棧中局部變量表中的引用的對象

3.方法區中類靜態屬性引用的對象

4.方法區中的常量引用的對象

要知道設置Survivor是爲了減少送到老年代的對象!!!

具體來說

   首先  堆=新生代+老年代,  其中  新生代爲 eden+ from +to  ,  eden:from:to=8:1:1 默認會這樣

   

堆內存劃分:

堆大小 = 新生代 + 老年代。堆的大小可通過參數–Xms(堆的初始容量)、-Xmx(堆的最大容量) 來指定。
其中,新生代 ( Young ) 被細分爲 Eden 和 兩個 Survivor 區域,這兩個 Survivor 區域分別被命名爲 from 和 to,以示區分。默認的,Edem : from : to = 8 : 1 : 1 。可以通過參數 –XX:SurvivorRatio 來設定 ,即:

Survivor區和Eden區的比值

-XX:SurvivorRatio=8 表示 兩個Eden :Survivor  = 8:2 ,每個Survivor佔 1/10

可以修改爲-XX:SurvivorRatio=2

2 表示 兩個Eden :Survivor  = 2: 2  ,各佔一半

JVM 每次只會使用 Eden 和其中的一塊 Survivor 區域來爲對象服務,所以無論什麼時候,總是有一塊 Survivor 區域是空閒着的。
新生代實際可用的內存空間爲 9/10 ( 即90% )的新生代空間。
 

minor gc:指發生在新生代的垃圾回收動作,因爲JAVA對象大多數都是朝生夕死的特性,所以minor gc非常平凡,使用複製算法快速的回收

老年代GC(major gc):指發生在老年代的垃圾回收動作,所採用是的標記--整理算法。

老年代幾乎都是經過survivor熬過來的,它們是不會那麼容易“死掉”,因此major gc不會想minor gc那樣頻繁

Full gc:minor gc + major gc

 

JVM相關往期博客:

Java虛擬機(JVM)原理篇

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