垃圾收集器與內(nèi)存分配策略(二)

前言

  • 對象的內(nèi)存分配,大多數(shù)都是在堆上分配的,但是有一些在JIT編譯后被拆散為標(biāo)量類型并間接地棧上分配(即進(jìn)行了優(yōu)化)。在堆上,對象會被分配在新生代(主要)和老年代(少數(shù))中,但是如果啟動了本地線程分配緩沖(-XX:+/-UseTLAB參數(shù)指定),將按線程優(yōu)先在TLAB上分配。
  • 注:分配規(guī)則不是固定的,具體細(xì)節(jié)取決于當(dāng)前使用的是哪一種垃圾收集器組合,還有虛擬機(jī)中與內(nèi)存相關(guān)的參數(shù)設(shè)置
  • 下面講解幾條最普遍的內(nèi)存分配規(guī)則。

1.對象優(yōu)先在Eden分配

  • 堆上的大多數(shù)對象都是分配在新生代中,因?yàn)樾律捎玫氖菑?fù)制算法,新生代中分為一個Eden區(qū)和兩個Survivor區(qū),分配時會分配在Eden區(qū)和其中一個Survivor區(qū),當(dāng)Eden+1個Survivor區(qū)沒有足夠空間分配時虛擬機(jī)將發(fā)起一次MinorGC。此次收集會將Eden+1個Survivor區(qū)中不可達(dá)對象進(jìn)行回收,并將存活的對象放入到另一個Survivor區(qū)中,然后再清理剛才使用的Eden+1個Survivor區(qū)。注:如果Survivor區(qū)存不下Eden+1個Survivor區(qū)中存活下來的對象,就會采用分配擔(dān)保機(jī)制,將存活下來的對象轉(zhuǎn)移到老年代中。然后再清理剛才使用的Eden+1個Survivor區(qū)。

2.大對象直接進(jìn)入老年代

  • 所謂的大對象是指,需要大量連續(xù)內(nèi)存空間的Java對象,最典型的大對象就是那種很長的字符串以及數(shù)組。
  • 虛擬機(jī)提供了一個-XX:PretenureSizeThreshold參數(shù),令大于這個設(shè)置值的對象直接在老年代分配。這樣做的目的是避免在Eden區(qū)及兩個Survivor區(qū)之間發(fā)生大量的內(nèi)存復(fù)制(復(fù)習(xí)一下:新生代采用復(fù)制算法收集內(nèi)存)。

3.長期存活對象進(jìn)行老年代

  • 既然虛擬機(jī)采用了分代收集的思想來管理內(nèi)存,那么內(nèi)存回收時就必須能識別哪些對象應(yīng)放在新生代,哪些對象應(yīng)放在老年代中。為了做到這點(diǎn),虛擬機(jī)給每個對象定義了一個對象年齡(Age)計(jì)數(shù)器。如果對象在Eden出生并經(jīng)過第一次Minor GC后仍然存活,并且能被Survivor容納的話,將被移動到Survivor空間中,并且對象年齡設(shè)為1。對象在Survivor區(qū)中每“熬過”一次Minor GC,年齡就增加1歲,當(dāng)它的年齡增加到一定程度(默認(rèn)為15歲),就將會被晉升到老年代中。
  • 對象晉升老年代的年齡閾值,可以通過參數(shù)-XX:MaxTenuringThreshold設(shè)置。

4.動態(tài)對象年齡判定

  • 為了能更好地適應(yīng)不同程序的內(nèi)存狀況,虛擬機(jī)并不是永遠(yuǎn)地要求對象的年齡必須達(dá)到了MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代,無須等到MaxTenuringThreshold中要求的年齡。

空間分配擔(dān)保

  • 在發(fā)生Minor GC之前,虛擬機(jī)會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間,如果這個條件成立,那么Minor GC可以確保是安全的。如果不成立,則虛擬機(jī)會查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗。如果允許,那么會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于,將嘗試著進(jìn)行一次Minor GC,盡管這次Minor GC是有風(fēng)險的;如果小于,或者HandlePromotionFailure設(shè)置不允許冒險,那這時也要改為進(jìn)行一次Full GC。
  • **注:Minor GC和Full GC有什么不一樣嗎?
    新生代GC(Minor GC):指發(fā)生在新生代的垃圾收集動作,因?yàn)镴ava對象大多都具備朝生夕滅的特性,所以Minor GC非常頻繁,一般回收速度也比較快。
    老年代GC(Major GC/Full GC):指發(fā)生在老年代的GC,出現(xiàn)了Major GC,經(jīng)常會伴隨至少一次的Minor GC(但非絕對的,在Parallel Scavenge收集器的收集策略里就有直接進(jìn)行Major GC的策略選擇過程)。Major GC的速度一般會比Minor GC慢10倍以上。
    **
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容