1. 程式人生 > >JVM知識總結--記憶體分配策略

JVM知識總結--記憶體分配策略

物件的記憶體分配主要是在堆上進行的,也有可能在JIT編譯後被拆散為標量型別並間接的在棧上分配,物件主要分配在Eden區,如果啟動了TLAB,則優先分配到TLAB上,少數情況下可能直接分配到老年代中;總的來說物件的分配有大致的規則和模式,但無一定之規,具體的分配邏輯與使用的GC收集器型別和配置的JVM引數都會有關係。

Minor GC 和 Full GC

  1. Minor GC:發生在新生代的垃圾收集動作,頻率高、速度快;
  2. Full GC/Major GC:發生在老年代的GC,通常會伴隨至少一次的Minor GC,一般會比Minor GC慢10倍以上;

最普遍的幾條記憶體分配原則如下:

  1. 物件優先在Eden區分配
    :當Eden區沒有足夠的空間時,虛擬機器會發起一次Minor GC;
  2. 大物件直接進入老年代:大物件是指需要大量連續記憶體空間的物件,典型的大物件就是很長的字串或陣列,虛擬機器提供了-XX:PretenureSizeThreshold引數(僅針對Serial和Par New收集器有效),大於此設定值的物件會直接放入老年代;
  3. 長期存活的物件將進入老年代:為了在記憶體回收時識別哪些物件放在年輕代,哪些放在老年代,VM給每個物件定義了一個物件年齡計數器(Age),物件在第一次Minor GC後仍存活並被移動到Survivor中後Age會被設為1,以後每經過一次Minor GC age都會加1,age增加到15(預設值)後,物件會被移動到老年代中,物件晉升到老年代的age閾值可以通過-XX:MaxTenuringThreshold來設定;
  4. 動態物件年齡判定:為了更好的適應不同程式的記憶體情況,如果在Survivor空間中相同年齡的所有物件大小總和大於Survivor空間的一半,則年齡大於等於此年齡的物件可以忽略3中的配置直接進入老年代;
  5. 空間分配擔保:在發生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。