轉載請注明原文地址:http://www.cnblogs.com/ygj0930/p/6535893.html
在虛擬機中,我們知道對象的內存是分配在堆中的。但是堆又可以划分為更小的區域以便垃圾回收,那么,對象到底是怎么在分配在堆中的呢?
一:對象優先分配在線程的本地分配緩沖區
在前面我們提到,每個線程可以在堆中預先分配得到一片區域,作為本地線程分配緩沖區(TLAB)。當該線程執行時,有對象創建的話,就在該線程的TLAB中分配內存。當該線程的TLAB用完了才申請堆中的空閑內存。
二:堆中優先分配Eden
大多數情況下,對象都在新生代的Eden區中分配內存。而因為大部分的對象都是“朝生夕死”的,所以新生代又會頻繁進行垃圾回收。
三:大對象直接進入老年代
需要大量連續空間的對象,如:長字符串、數組等,會直接在老年代分配內存。這是因為,這樣可以避免在新生代區頻繁的GC時發生大量的內存賦值(新生代的GC是采用復制算法的)。
四:長期存活的對象“晉入”老年代
新生代中經歷了多次GC仍然存活的對象,當年齡達到一定程度(默認15)時就會晉升到老年代。
為了更好地適應內存情況,虛擬機不是要求對象必須到達閥值才可晉升老年代的,而是采用動態年齡判定的方法:如果Servivor空間中相同年齡的對象大小大於Servivor空間的一般時,由於下一次的MinorGC時,這些對象如果仍然存活的話,復制到ToServivor空間時就放不下了。所以,在本次GC時就可以把這些對象以及年齡大於等於這些對象的直接進入老年代。
在MinorGC時,如果Eden和FromServivor中存活的對象在復制到ToServivor時放不下了,也會直接分配到老年代。
五:空間分配擔保
在MinorGC之前,會先檢查老年代最大可用空間是否可以容納新生代所有對象(防止新生代全部晉升時放不下),如果可以容納,則MinorGC可以安全執行。否則,檢查是否允許擔保失敗,是則檢查老年代最大可用空間是否大於歷次晉升到老年代的對象的平均大小,是則嘗試進行MinorGC;小於或者MinorGC失敗,則會發起一次FullGC清理老年代。