1. 程式人生 > >JVM:新生代老年代和GC

JVM:新生代老年代和GC

        Java堆可以分為新生代和老年代兩個區,其中新生代又可以分為一個Eden區和兩個Survivor區,兩個Survivor區分別被命名為From和To以示區分,新生代和老年代的比例為1:2,它們共同組成堆的記憶體區,所以新生代佔堆的1/3,老年代佔2/3,但這個比例可以修改,下面分別來介紹一下新生代和老年代。

 

一、【新生代】

        我們先來屢屢,為什麼需要把堆分代?不分代不能完成他所做的事情麼?其實不分代完全可以,分代的唯一理由就是優化GC效能。你先想想,如果沒有分代,那我們所有的物件都在一塊,GC的時候我們要找到哪些物件沒用,這樣就會對堆的所有區域進行掃描。而我們的很多物件都是朝生夕死的,如果分代的話,我們把新建立的物件放到某一地方,當GC的時候先把這塊存“朝生夕死”物件的區域進行回收,這樣就會騰出很大的空間出來。

        新生代分為三個區域,一個Eden區和兩個Survivor區,它們之間的比例為(8:1:1),這個比例也是可以修改的。通常情況下,物件主要分配在新生代的Eden區上,少數情況下也可能會直接分配在老年代中。Java虛擬機器每次使用新生代中的Eden和其中一塊Survivor(From),在經過一次Minor GC後,將Eden和Survivor中還存活的物件一次性地複製到另一塊Survivor空間上(這裡使用的複製演算法進行GC),最後清理掉Eden和剛才用過的Survivor(From)空間。將此時在Survivor空間存活下來的物件的年齡設定為1,以後這些物件每在Survivor區熬過一次GC,它們的年齡就加1,當物件年齡達到某個年齡(預設值為15)時,就會把它們移到老年代中。

        在新生代中進行GC時,有可能遇到另外一塊Survivor空間沒有足夠空間存放上一次新生代收集下來的存活物件,這些物件將直接通過分配擔保機制進入老年代

 

總結:

1、Minor GC是發生在新生代中的垃圾收集,採用的複製演算法;

2、新生代中每次使用的空間不超過90%,主要用來存放新生的物件;

3、Minor GC每次收集後Eden區和一塊Survivor區都被清空;

 

二、【老年代】

        老年代裡面存放都是生命週期長的物件,對於一些較大的物件(即需要分配一塊較大的連續記憶體空間),是直接存入老年代的,還有很多從新生代的Survivor區域中熬過來的物件。

        老年代中使用的是Full GC,Full GC所採用的是標記-整理演算法。老年代中的Full GC不像Minor GC操作那麼頻繁,並且進行一次Full GC所需要的時間要比Minor GC的時間長。

 

總結:

1、老年代中使用Full GC,部分採用的標記-整理演算法

 

三、一個物件的這一輩子

        我是一個普通的Java物件,我出生在Eden區,在Eden區我還看到和我長的很像的小兄弟,我們在Eden區中玩了挺長時間。有一天Eden區中的人實在是太多了,我就被迫去了Survivor區的“From”區,自從去了Survivor區,我就開始漂了,有時候在Survivor的“From”區,有時候在Survivor的“To”區,居無定所。直到我18歲的時候,爸爸說我成人了,該去社會上闖闖了。於是我就去了年老代那邊,年老代裡,人很多,並且年齡都挺大的,我在這裡也認識了很多人。在年老代裡,我生活了20年(每次GC加一歲),然後被回收。