0


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

一、前言

    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)。

标签: jvm java

本文转载自: https://blog.csdn.net/qq_59616295/article/details/126918548
版权归原作者 记得爱蓝色 所有, 如有侵权,请联系我们删除。

“创建对象在堆区如何分配内存”的评论:

还没有评论