堆内存分配策略

概述

  • 如果对象在Eden出生并经过第一次Minor GC后依然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,把那个将对象年龄设为1,对象在Survivor区中每熬过一次MinorGC,年龄就增加一岁,当它的年龄增加到一定程度(默认15岁,其实每个JVM、每个GC都有所不同)时,就会被晋升到老年代中
  • 对象晋升老年代的年龄阈值,可以通过选项-XX:MaxTenuringThreshold来设置
  • 针对不同年龄段的对象分配原则如下
    • 优先分配到Eden
    • 大对象直接分配到老年代,尽量避免程序中出现过多的大对象
    • 长期存活的对象分配到老年代
    • 动态对象年龄判断:如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入到老年代,无需等到MaxTenuringThreshold中要求的年龄
    • 空间分配担保:-XX: HandlePromotionFailure

 

 

 代码

/** 测试:分配60m堆空间,新生代 20m ,Eden 16m, s0 2m, s1 2m,buffer对象20m,Eden 区无法存放buffer, 直接晋升老年代
 * -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails
 */
public class YoungOldAreaTest {
    // 新生代 20m ,Eden 16m, s0 2m, s1 2m
    // 老年代 40m
    public static void main(String[] args) {
        //Eden 区无法存放buffer  晋升老年代
        byte[] buffer = new byte[1024 * 1024 * 20];//20m
    }
}

 小结

  • 年轻代是对象的诞生、生长、消亡的区域,一个对象在这里产生、应用、最后被垃圾回收器收集、结束生命

  • 老年代放置长生命周期对象,通常都是从Survivor区域筛选拷贝过来的Java对象。当然,也有特殊情况,我们知道普通的对象会被分配在TLAB上,如果对象较大,JVM会试图直接分配在Eden其他位置上;如果对象太大,完全无法在新生代找到足够长的连续空闲空间,JVM就会直接分配到老年代

  • 当GC只发生在年轻代中,回收年轻对象的行为被称为MinorGC。当GC发生在老年代时则被称为MajorGC或者FullGC。一般的,MinorGC的发生频率要比MajorGC高很多,即老年代中垃圾回收发生的频率大大低于年轻代

 

附:JVM学习目录

posted @ 2020-06-09 17:21  叮叮叮叮叮叮当  阅读(528)  评论(0编辑  收藏  举报