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


    目录

    一、前言

    二、什么是堆区(Heap)

    三、什么是新生代和老年代

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


    一、前言

            Java运行时内存区主要分为 运行时栈(虚拟机栈)、本地方法栈、程序计数器、堆空间、方法区(JDK1.8之后是元空间),今天来聊一聊我们的堆。
            一个对象或者数组的创建是在堆空间中完成的,堆的大小是有限的(固定的),所以,必不可少的我们要考虑一下堆的空间分配问题和对象的分配问题。

    二、什么是堆区(Heap)

     JVM虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。Heap堆是JVM 所管理的内存中最大的一块区域,被所有线程共享的一块内存区域。堆区中存放对象实例,“几乎”所有的对象实例以及数组都在这里分配内存

    三、什么是新生代和老年代

    堆是垃圾回收器的主要管理区域,JVM在划分堆区时,为了更好的进行垃圾回收,因此划分了新生代和老年代。

    由上图可知:堆区大小 = 新生代 + 老年代

    新生代占整个堆区的1/3,新生代又被分成了两部分:Eden区和Survivor区,Eden区占80%。两个Survivor区各占10%。

    老年代占堆区的2/3。

    对象在Eden区分配内存空间,在经历一次垃圾回收后,如果对象还存活就会转移至幸存者区,并且对象的年龄会+1,当年龄增加超过15岁时,就会晋升成老年代。

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

    创建一个新的java对象,在堆区分配内存,那么在堆中是如何分配内存的呢?

    首先先了解两种垃圾回收:

    • 新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;
    • 老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC 在有的时候中也代指整堆收集

    我们再看如下图:

    1、创建对象时,一开始时分配在Eden区,首先先判断Eden区是否放得下,如果可以放下,就会分配内存空间,反之执行一次YGC(Minor GC),对Eden区进行一次清除。

    值得注意的是:在经历YGC的过程中,依然存活的对象将会被转移到幸存者区,幸存者区又分为from和to两块区域,它们将存活的对象复制到未使用的Survivor 空间(from 或 to),然后将当前正在使用的空间完全清除,交换两块空间的使用状态。每次交换时,对象的年龄会加+1

    然后会判断幸存者区是否放得下,如果可以放得下,存入from或者to,如果放不下直接晋升老年代,存放在老年代区。

    2、在执行完一次YGC后再次判断Eden区是否放的下,如果可以放下,存入Eden区。

    3、如果Eden区放不下,判断老年区是否可以放下,可以放下时,分配给老年代。

    4、如果老年区放不下进行一次FGC(Major GC),清除过后再次判断,如果可以存入,分配给老年代,否则 OOM(OutOfMemoryError)。

  • 相关阅读:
    LyScript 内存交换与差异对比
    Python中的两种排序方法:sort()和sorted()
    【leetcode】【剑指offer Ⅱ】067. 最大的异或
    学内核之十二:从slab内存管理想到的
    生产环境 /dev/vda1文件满了导致redis无法写入问题分析 以及df -h解析
    供应原厂电流继电器 - HBDLX-21/3 整定电流范围0.1-1.09A AC220V
    VLAN 协议知识
    opensips使用drouting进行路由
    从理解路由到实现一套Router(路由)
    Pulsar 各个Shedder分析及新的Shedder -- AvgShedder
  • 原文地址:https://blog.csdn.net/qq_59616295/article/details/126918548