jvm的新生代和老年代簡介

iechenyb_發表於2018-03-02

新生代分為三個區域,一個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.Eden區

    Eden區位於Java堆的年輕代,是新物件分配記憶體的地方,由於堆是所有執行緒共享的,因此在堆上分配記憶體需要加鎖。而Sun JDK為提升效率,會為每個新建的執行緒在Eden上分配一塊獨立的空間由該執行緒獨享,這塊空間稱為TLAB(Thread Local Allocation Buffer)。在TLAB上分配記憶體不需要加鎖,因此JVM在給執行緒中的物件分配記憶體時會盡量在TLAB上分配。如果物件過大或TLAB用完,則仍然在堆上進行分配。如果Eden區記憶體也用完了,則會進行一次Minor GC(young GC)。

 

2.Survival from to

    Survival區與Eden區相同都在Java堆的年輕代。Survival區有兩塊,一塊稱為from區,另一塊為to區,這兩個區是相對的,在發生一次Minor GC後,from區就會和to區互換。在發生Minor GC時,Eden區和Survivalfrom區會把一些仍然存活的物件複製進Survival to區,並清除記憶體。Survival to區會把一些存活得足夠舊的物件移至年老代。

 

3.年老代

    年老代裡存放的都是存活時間較久的,大小較大的物件,因此年老代使用標記整理演算法。當年老代容量滿的時候,會觸發一次Major GC(full GC),回收年老代和年輕代中不再被使用的物件資源。


總結:

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

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

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

4、老年代中使用Full GC,採用的標記-清除演算法

注意:

堆=新生代+老年代,不包括永久代(方法區)。

很多人認為方法區(或者HotSpot虛擬機器中的永久代)是沒有垃圾收集的,Java虛擬機器規範中確實說過可以不要求虛擬機器在方法區實現垃圾收集,而且在方法區進行垃圾收集的“價效比”一般比較低:在堆中,尤其是在新生代中,常規應用進行一次垃圾收集一般可以回收70%~95%的空間,而永久代的垃圾收集效率遠低於此。

永久代的垃圾收集主要回收兩部分內容:廢棄常量和無用的類。回收廢棄常量與回收Java堆中的物件非常類似。以常量池中字面量的回收為例,假如一個字串“abc”已經進入了常量池中,但是當前系統沒有任何一個String物件是叫做“abc”的,換句話說是沒有任何String物件引用常量池中的“abc”常量,也沒有其他地方引用了這個字面量,如果在這時候發生記憶體回收,而且必要的話,這個“abc”常量就會被系統“請”出常量池。常量池中的其他類(介面)、方法、欄位的符號引用也與此類似。

判定一個常量是否是“廢棄常量”比較簡單,而要判定一個類是否是“無用的類”的條件則相對苛刻許多。類需要同時滿足下面3個條件才能算是“無用的類”:

該類所有的例項都已經被回收,也就是Java堆中不存在該類的任何例項。

載入該類的ClassLoader已經被回收。

該類對應的java.lang.Class 物件沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

虛擬機器可以對滿足上述3個條件的無用類進行回收,這裡說的僅僅是“可以”,而不是和物件一樣,不使用了就必然會回收。是否對類進行回收,HotSpot虛擬機器提供了-Xnoclassgc引數進行控制,還可以使用-verbose:class及-XX:+TraceClassLoading、 -XX:+TraceClassUnLoading檢視類的載入和解除安裝資訊。

在大量使用反射、動態代理、CGLib等bytecode框架的場景,以及動態生成JSP和OSGi這類頻繁自定義ClassLoader的場景都需要虛擬機器具備類解除安裝的功能,以保證永久代不會溢位。


相關文章