• 创建对象在堆区如何分配内存


    对于Java来说,它有着虚拟机自动内存管理机制,不再像c/c++那样,需要开发者手动管理内存。在Java中数据类型分为基本数据类型和引用数据类型。基本类型数据保存在“栈中”,引用数据类型保存在“堆中”,我们先来了解一下Java程序运行时数据区域的划分。

    在JDK 1.8之前分为:线程共享Heap堆区、Method Area方法区)、线程私有(虚拟机栈、本地方法栈、程序计数器)

    JDK 1.8以后分为:线程共享Heap堆区、MetaSpace 元空间)、线程私有(虚拟机栈、本地方法栈、程序计数器

     

     Java虚拟机

    Java虚拟机栈是由一个个的栈帧组成,每个栈帧中都有:局部变量表、操作数栈、动态链接、方法出口信息。包括main()方法,每一次方法调用都会有一个对应的栈帧被压入虚拟机栈、每一个方法调用结束之后,代表该方法的栈帧都会从虚拟机栈中被弹出。在运行的线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,代表当前正在执行的方法。程序运行时,所有的指令只能对当前栈帧进行操作。

    当我们使用Cat cat = new Cat()创建一个对象时,在虚拟机栈中的当前活动栈帧的局部变量表中就会存储这个对象的引用cat ,而通过new 创建出来的对象,则是被存储在堆中,这个cat引用着堆中的对象。我们继续来了解一下堆的结构。

    堆(Heap)

    堆区是JVM所管理的内存中最大的一块,所有的对象都是存储在堆中。堆区分为新生代(1/3堆区空间)、老年代(2/3堆区空间)。新生代又分为Eden伊甸区(8/10新生代空间)、from幸存者区(1/10新生代空间)、to幸存者区(1/10新生代空间)

    对象分配内存 

    创建一个新对象,Eden区就是对象最开始诞生的区域;

    如果Eden区内存充足时,虚拟机直接为其分配内存;

    当Eden区存储满时,将一部分对象存储至s0区,当触发YGC回收机制时,又会将对象存储至s1,连同s0中的对象存储至s1中。当对象从s0至s1的过程中对象的年龄则会+1,当对象的年龄超出15岁,则该对象将会被存储值老年代;

    如果Eden区没有那么大的内存存储该对象,则触发YGC垃圾回收机制,通过整理Eden区的内存判断该对象是否可以被存储;

    如果通过YGC回收机制后发现Eden区有足够的空间可以存储该对象,则为其分配空间;

    如果已经触发YGC机制并回收了,内存空间依旧不充足,则考虑将其存储至老年代;

    如果老年代的内存充足,则为其分配空间;

    如果老年代的内存依旧不足以存储该对象,则触发FULL GC回收机制,通过整理老年代的内存,判断该空间是否可以存储该对象;

    如果可以存储该对象,则为其分配空间;

    如果还不可以存储该对象,那么该对象已经超出内存所剩的空间,则抛出“内存溢出的异常”;

  • 相关阅读:
    第12章 最佳的UI体验——Material Design实战
    Flink 任务失败重启与恢复策略
    JavaS
    视觉slam十四讲学习笔记(四)相机与图像
    【零基础入门SpringMVC】第五期——报文、文件转移、拦截器、异常处理器
    怎样构建符合HIPAA的服务?
    【音视频】srs直播平台搭建
    MATLAB初学者入门(15)—— 随机森林
    公共经济学名词解释
    读书笔记《蛤蟆先生去看心理医生》
  • 原文地址:https://blog.csdn.net/m0_59340907/article/details/126915942