對象的內存分配主要是在堆上進行的,也有可能在JIT編譯後被拆散爲標量類型並間接的在棧上分配,對象主要分配在Eden區,若是啓動了TLAB,則優先分配到TLAB上,少數狀況下可能直接分配到老年代中;總的來講對象的分配有大體的規則和模式,但無必定之規,具體的分配邏輯與使用的GC收集器類型和配置的JVM參數都會有關係。數組
Minor GC 和 Full GC
- Minor GC:發生在新生代的垃圾收集動做,頻率高、速度快;
- Full GC/Major GC:發生在老年代的GC,一般會伴隨至少一次的Minor GC,通常會比Minor GC慢10倍以上;
最廣泛的幾條內存分配原則以下:
- 對象優先在Eden區分配:當Eden區沒有足夠的空間時,虛擬機會發起一次Minor GC;
- 大對象直接進入老年代:大對象是指須要大量連續內存空間的對象,典型的大對象就是很長的字符串或數組,虛擬機提供了-XX:PretenureSizeThreshold參數(僅針對Serial和Par New收集器有效),大於此設置值的對象會直接放入老年代;
- 長期存活的對象將進入老年代:爲了在內存回收時識別哪些對象放在年輕代,哪些放在老年代,VM給每一個對象定義了一個對象年齡計數器(Age),對象在第一次Minor GC後仍存活並被移動到Survivor中後Age會被設爲1,之後每通過一次Minor GC age都會加1,age增長到15(默認值)後,對象會被移動到老年代中,對象晉升到老年代的age閾值能夠經過-XX:MaxTenuringThreshold來設置;
- 動態對象年齡斷定:爲了更好的適應不一樣程序的內存狀況,若是在Survivor空間中相同年齡的全部對象大小總和大於Survivor空間的一半,則年齡大於等於此年齡的對象能夠忽略3中的配置直接進入老年代;
- 空間分配擔保:在發生Minor GC前,vm會先檢查老年代的最大可用連續空間是否大於新生代對象的總空間,若是小於,虛擬機會查看HandlePromotionFailure是否容許擔保失敗,若是容許,vm會繼續檢查老年代的最大可用連續空間是否大於歷次晉升到老年代的對象的平均大小,若是大於,將會嘗試進行一次Minor GC,若是小於或HandlePromotionFailure設置爲不容許失敗,會先進行一次Full GC,總的來講,這是爲了保證在Minor GC發生時老年代有足夠的連續空間存放可能會重新生代晉升來的對象而採起的一項措施,爲了不頻繁的Full GC,HandlePromotionFailure一般會被設置爲True;另外,在JDK 6 Update 24以後,HandlePromotionFailure參數再也不生效,只要老年代的可用連續空間大於新生代對象總和或歷次晉升的平均大小,就會進行Minor GC,不然進行Full GC。