Java虚拟机内存分配和回收策略

时间:2021-10-19 16:24:56

1 对象优先分配在Eden区

  对象优先在Eden进行分配,大多数情况下,对象在新生代Eden区进行分配。当Eden区没有足够的空间进行分配时,虚拟机会发起一次Minor GC。

  新生代GC(Ninor GC)指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕死的特征,因此Minor GC非常频繁,一般回收速度也比较快

    老年代GC(Major GC / Full GC)指发生在老年代的GC,出现在Major GC,经常会伴随至少一次的Minor GC。Major GC的速度一般会比Minor GC慢至少十倍。

2 大对象直接进入老年代

  所谓大对象是指需要大量连续内存的Java对象,最典型的大对象就是那种很长的字符串以及数组,因为出现大对象对于内存来说是一个很坏的消息,因此一般需要放到老年代中进行维护。

3 长期存活的对象将进入老年代

 既然虚拟机采用了分代收集的思想来管理内存,那么内存必须能够分辨出那些对象应该放在新生代,哪个放在老年代。因此,虚拟机提出了对象年龄计数器。若对象在 Eden诞生,熬过了一次Minor GC后被Survivor收容,则对象年龄设为1。然后在Survivor中熬过14次Minor GC后,则可以晋升到老年代。

4 动态对象年龄判定

 进行年龄判定的时候,未必一定要熬到门限值再进行垃圾回收,如果Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

5 空间分配担保

 在发生Minor GC之前,虚拟机会先检查老年代中最大可用的连续空间是否大于新生代所有对象总空间,若这个条件成立,那么Minor GC就可以确保是安全的。如果不成立,则查看handlePromotionFailure设置值是否允许担保失败,若允许,则继续检查老年代最大可用的连续空间是否大于历次晋升到老年代的对象的平均大小。若大于则尝试进行一次Minor GC;若小于或者不允许,则尝试进行一次Full GC。