深入理解Java虚拟机之读书笔记三 内存分配策略

时间:2023-03-08 22:35:19

  一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配。对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分配在老年代中,分配的规则并不是百分之百固定的。细节取决于哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数的设置。

  一、对象优先在Eden分配

  优先在新生代的Eden区中分配,当不够时,发起一次Minor GC。

  二、大对象直接进入老年代

  需要连续大量内存空间的Java对象,长字符串和数组等。

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

  虚拟机给每个对象定义了一个对象年龄计数器。Eden区的对象,经过一次Minor GC后,如果能进入Survivor区,年龄为1,以后没经过一次Minor GC,年龄加1,默认到15时进入老年代。可参数调节阈值。

  四、动态对象年龄判定

  如果在Survivor中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等阈值年龄。

  五、空间分配担保

  在发生Minor GC前,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,改为直接进行Full GC。如果小于,检查HandlePromotionFailure设置是否允许担保失败;如果允许,只Minor GC;或者Full GC。

  如果发生了HandlePromotionFailure失败,失败后发起一次Full GC,默认允许担保失败。