• 【JVM】年轻代进入老年代规整


    大对象直接进入老年代

    然而实际在开发中,并不是所有对象都能这样进行GC流程。当对象过大时或特别大时,因为占用幸存者区空间过大或大于幸存者区,而造成反复GC,重复复制大对象增加GC时间问题,当然JVM对这方面有专门的优化。而这个机制就是大对象直接进入老年代,使用JVM参数-XX:PretenureSizeThreshold(单位为字节)设置大对象的大小,如果对象超过设置的大小会直接进入老年代,防止大对象进入年轻代造成重复GC。

    • 大对象

      大对象就是需要大量连续内存空间的对象,即数组,字符串。

    注意:该参数只在Serial和ParNew收集器才会生效,即Serial与ParNew存在该参数进行大对象区分。
    补充: -XX:+UseSerialGC采用Serial收集器

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

    JVM采用分代收集来实现内存管理,就必须区分不同对象进入不同代中进行不同的处理,而JVM的解决方法是:给每一个对象设置对象头中的对象年龄计数器(Age)
    对象流程:

    • 经历过Minor GC,能够进入Survivor(幸存者区),则设置对象年龄为1
    • 对象每经历过一次MinorGC,对象年龄就会加一
    • 当年龄增加到达一定大小(默认15,CMS收集器默认6,其他不同的收集器会有所不同),将会进入老年代。

    设置进入老年代年龄阈值: -XX:MaxTenuringThreshold

    对象动态年龄判断

    在JVM中还有一种年龄判断机制:当一批对象的总大小大大于Survivor区域的50%,此时大于该批对象中的最大年龄的对象,直接进入老年代。

    • 当minor gc后对象总和大于Survivor区域的50%,进行
    • 该操作一般会在minor gc后进行触发
    • 可以通过JVM参数-XX:TargetSurvivorRatio进行指定

    该机制是为了使多次进行GC后还存在的对象更早进入老年代,至于为什么是大于50%Survivor区的对象,实际上Eden区和Survivor区中很少存在3,4次还幸存对象
    其实就是一种根据经验来将迟早会进入老年代的对象提前进入

    老年代空间分配担保机制

    • 年轻代进行minor gc之前计算老年代剩余可用空间
    • 当年轻代在minor gc前所有的对象大小之和大于老年代剩余可用空间

      如果配置JVM参数-XX:-HandlePromotionFailure

      • 判断当前老年代剩余可用空间是否大于历史minor gc进入老年代的对象平均大小
      • 老年代剩余可用空间小于进入老年代对象的平均大小或未设置时,将触发Full gc
      • 老年代剩余可用空间大于进入老年代对象的平均大小时,触发minor gc,如果minor gc后存活并需要移动到老年代的对象总大小还是大于老年代的可用空间,也将会触发Full gc

        Full gc对老年代和年轻代一起回收垃圾,诺Full gc后老年代的可用空间还是无法存放minor gc后需要进入老年代的对象,将会抛出OOM错误。

    • 否则进行Full gc即可,而小于则minor gc
      在这里插入图片描述

    该机制是为了尽可能的减少Full gc,并且哪怕无法避免full gc也可以在一定程度上减少年轻代对老年代的引用,加快了GC效率

  • 相关阅读:
    Android-Q 对 startActivity() 做了限制,怎么适配?
    为什么mysql索引用B+树而不用Hash表
    第十一章《Java实战常用类》第3节:Math类
    【AI实践】Dify开发应用和对接微信
    卷积神经网络的工程技巧总结
    AWS中的HVM和PV格式的AMI的区别
    【go从入门到精通】常用标准库的用法
    Ubuntu22.04下安装kafka_2.12-2.6.0并运行简单实例
    主成分分析法(PCA)及其python实现
    C/C++小型文本查询引擎
  • 原文地址:https://blog.csdn.net/at10090/article/details/121736089