內存分配與回收技術

簡言

Java技術體系提倡的自動內存管理最終可以歸結爲自動化的解決了兩個問題:給對象分配內存以及回收分配給對象的內存。對象內存的分配,往大方向講,就是在堆上分配,對象主要分配在新生代的Eden區上,如果啓動本地線程分配緩衝,將按線程優先在TLAB上分配。少數情況下也可能直接進入老年代中。

  1. 對象優先分配在Eden區
    大多數情況下,對象在新生代Eden區中分配。當Eden區內存空間不夠分配時,虛擬機將發起一次MinorGC.
    新生代內存區域被劃分爲Eden、Survivor(form\to)三大區域,可通過參數對設定Eden與Survivor區域大小的比值
    新手代大多數情況下朝生夕死,因此MinorGC非常頻繁,一般回收速度也較快。
    MajorGC\FullGC經常會至少伴隨一次的MinorGC(但並非絕對,取決於具體的實現),FullGC較MinorGC要慢上10以上
  2. 大對象直接進入老年代
    所謂大對象是指需要大量連續內存空間的Java對象,最典型的就是很長的字符串以及數組。大對象的出現,經常會導致內存還有不少空間時就提前觸發垃圾收集以獲取足夠的連續空間來安置它們。
    虛擬機提供參數,令大於這個參數的對象直接在老年代分配。這樣做的目的是避免在Eden區及兩個Survivor區之間發生大量的內存複製(新生代採用內存複製算法)
  3. 長期存活的對象將進入老年代
    虛擬機爲每個對象設置一個年齡計數器。在Eden出生時,遇到第一次GC時年齡設定爲1,此後在Survivor區每遭遇一次GC年齡+1,當達到年齡閾值時自動進入老年區(閾值默認15,可自主設定)
  4. 動態對象年齡判斷
    爲更好地適應不同程序的內存情況,虛擬機並不是永遠地要求對象的年齡必須達到MaxTenuringThreshold才能晉升老年代,如果Survivor空間中相同年齡所有對象大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就可以直接進入老年代,無需達到設定年齡。
  5. 空間分配擔保
    在發生MinorGC之前,虛擬機會檢查老年代最大可用的連續空間是否大於新生代所有對象總空間,如果這個條件成立,那麼MinorGC可以確保是安全的。
    如果不成立,則查看虛擬機HandlePromotionFailure設置值是否允許擔保失敗
    如果允許,那麼會繼續檢查老年代最大連續可用空間是否大於歷次晉升到老年代對象的平均大小,如果大於則嘗試一次MinorGC,儘管這次GC有風險(該次晉升平均值比歷次大,MinorGC失敗,進入FullGC);
    如果小於或者HandlePromotionFailure不允許擔保失敗,這是要改爲進行一次FullGC
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章