浅谈java虚拟机对象内存分配与回收策略,MinorGC执行逻辑

  1. 对象优先在Eden区分配内存
           大多数情况下,对象在新生代Eden区中进行分配,当Eden区没有足够空间进行分配时,虚拟机将发起一次MinorGC(新生代垃圾回收)

  2. 大对象直接进入老年代
           大对象—需要大量连续内存空间的java对象。
           虚拟机提供的PretenureSizeThreshold参数,令大于这个设置值的对象,直接在老年代进行分配。
           目的:避免在Eden区及两个Survivor区之间发生大量的内存复制(新生代采用的是复制算法进行垃圾回收)

  3. 长期存活的对象进入老年区
           虚拟机定义了年龄(age)计数器,当在Eden区出生并经过一次MinorGC后仍存活的对象,并能被Survivor容纳,将被移动到Survivor空间中,年龄设置1,对象在Survivor中每熬过一次MinorGC年龄+1,默认15,当大于15时,被移动到老年代。

  4. 动态对象年龄判定
           Survivor中年龄相同的对象大小总和,大于Survivor空间的一半时,对象进入老年代。

  5. 空间分配担保
           空间分配担保发生在MinorGC时。MinorGC前,虚拟机检查老年代最大可用的连续空间是否大于新生代所有对象总和,大于就进行MinorGC。
           小于则判定HandlePromotionFailure设置值是否允许担保失败,如果允许则继续检查老年代最大可用的连续空间,是否大于历次MinorGC时,进入老年代的对象的平均值。大于,则进行一次风险的MinorGC,小于则FullGC(java堆整个进行一次垃圾清理)

  • 风险的MinorGC
           当老年代的空间可能不足的时候,进行的MinorGC即是一次风险的MinorGC
           why?
           ———因为新生代垃圾回收使用复制算法,为了提高内存利用率,只使用了其中一个Survivor进行备份轮换。因此当出现大量对象在MinorGC后还存活的情况,就需要老年代进行分配担保,把Survivor无法容纳的对象直接进入老年代。如果老年代的内存一但不足,则导致MinorGC失败。

以下是内存分配与回收策略的一个逻辑简图
浅谈java虚拟机对象内存分配与回收策略,MinorGC执行逻辑