• 堆内存分配策略


    概述

    • 如果对象在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学习目录

  • 相关阅读:
    R 语言
    Maven
    IntelliJ IDEA
    Windows Terminal
    pip
    批处理编程案例
    Windows DOS命令批处理脚本
    Day15 T1 库特的向量
    Day12 T1 少女觉
    Day10 T2 邦德
  • 原文地址:https://www.cnblogs.com/ding-dang/p/13073978.html
Copyright © 2020-2023  润新知