• Java内存模型——创建对象在堆区如何分配内存


    一、程序运行时的区域划分

            与c/c++程序不同,在运行Java程序时,内存的控制权是交给JVM管理的,而JVM在运行Java程序时会把内存划分为若干个不同的数据区域——线程共享区域和线程私有区域,其中:

            线程私有区域分为虚拟机栈、本地方法栈和程序计数器;

            线程共享区域在JDK1.8之前分为 Heep 堆区 和 Method Area 方法区,在JDK1.8之后分为 Heep堆区 和 MetaSpace元空间。

    二、Heep堆区

            Heep堆区是JVM管理的内存中最大的一块区域,堆区被所有线程所共享,一般程序中创建的对象、数组都会在堆区分配内存。也是垃圾回收器GC管理的主要区域。因为目前垃圾回收算法都采用分代垃圾收集算法,所以堆区也进行了分代划分:新生代和老年代,其中新生代占整个堆区内存的1/3,老年代占整个堆内存的2/3。

          

            新生代又划分为Eden区和两个Survivor幸存者区from、to(有的叫法称为s0、s1) 一般新创建的对象会被放在这里,Eden区占整个新生代区的8/10,from和to分别各占1/10。

     三、创建对象时的内存分配

    创建一个新对象时:

            首先会在Eden区中分配空间,若内存空间足够,则为该对象分配内存;

            当Eden中内存不足时,会执行一次YGC(minor GC)回收没有被引用的对象,将被引用的对象(未被回收的对象)存入from幸存者区,此时再判断Eden区的内存是否足够,足够则分配内存;

            不足,则判断老年代是否放得下,若放得下则在老年代为该对象分配内存;

            若老年代还放不下,则会执行FGC(major GC)清理堆区垃圾(未被引用的对象),结束后再判断是否能存下,能,则在老年代分配内存;

            否则会OOM(OutOfMemoryError),产生堆内存溢出错误。

    PS:下面详细讲讲YGC的过程

            执行YGC时,是将Eden区中存储的旧对象实行清楚策略,把那些没有被引用的对象视为"垃圾",然后清除,剩余被使用的对象(未被清理)若from幸存者区存的下,则会被放入幸存者区,若这些未被清理的旧对象过大,则会被直接放入老年代。

            当下一次执行YGC时,存放在from幸存者区的对象若还未被清理,该对象对象头中的age+1,则会连同本次从Eden区中幸存的对象一起被存入to幸存者区(下一次YGC后的幸存者又会被挪入from区,可以理解为from和to交替使用,总有一个是空的),同样,若放不下,则会直接存入老年代。以此类推,当对象的年龄>15时,也会从幸存者区拿出放入老年代。

  • 相关阅读:
    渗透测试中的前端调试(上)
    好心情平台:抑郁症vs精分,如何治疗更有效?
    关于django的一些基础问答
    Serialiable接口和serialVersionUID的作用及其在redisson中的应用
    解决2K/4K高分屏下Vmware等虚拟机下Kail Linux界面显示问题
    深扒,Java性能调优手册:编程+多线程+JVM+设计模式+数据库+实战
    2013 ~【VUE+ ElementUI】——【上传、下载】进度计算
    Android RecyclerView BaseSectionQuickAdapter实现分组功能
    MySQL : 彻底搞懂一条SQL的执行过程
    douyin【商品抢购js脚本】
  • 原文地址:https://blog.csdn.net/wan25110712/article/details/126922021