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

目录

一,堆(Heap)

二、新生代、老年代

三、创建对象的内存分配


一,堆(Heap)

        Heap 堆区,用于存放对象实例和数组。

        Heap 堆是 JVM 所管理的内存中最大的一块区域,被所有线程共享的一块内存区域。 堆区中存放对象实例,“几乎”所有的对象实例以及数组都在这里分配内存。 堆(Heap) Heap 堆区,用于存放对象实例和数组 Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分 配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出),那么对象可以直接在栈上分配内存。

二、新生代、老年代

           Heap 堆是垃圾收集器 GC ( Garbage Collected )管理的主要区域,因此堆区也被 称作 GC 堆( Garbage Collected Heap )。从垃圾回收的角度,由于现在收集器基本都 采用分代垃圾收集算法,所以 JVM 中的堆区往往进行分代划分,例如:新生代 和 老年代。 目的是更好地回收内存,或者更快地分配内存。 

        Heap 堆区中的新生代、老年代的空间分配比例,可以通过 java -XX:+PrintFlagsFinal -version 命令查 看:如图 

 输出结果分析:

        InitialSurvivorRatio = 8 新生代 Young(Eden/Survivor) 空间的初始比例 = 8:代表 Eden 占新生代空间的 80% ; uintx NewRatio = 2 老年代 Old / 新生代 Young 的空间比例 = 2 : 代表老年代 Old 是新生代 Young 的2 倍 因为新生代是由 Eden + s0 + s1 组成的,所以按照上述默认比例,如果 Eden 区 内存大小是 40M,那么两个 Survivor 区就是 5M,整个新生代区就是 50M,然后可以算出 Old 区内存大小是 100M,堆区总大小就是 150M。

三、创建对象的内存分配

        创建一个新对象,在堆中的分配内存。 大部分情况下,对象会在 Eden 区生成,当 Eden 区装填满的时候,会触发 Young Garbage Collection ,即 YGC 垃圾回收的时候,在 Eden 区实现清除策略,没有被引 用的对象则直接回收。 依然存活的对象会被移送到 Survivor 区。 Survivor 区分为 s0 (from)和 s1(to) 两块内存 区域。每次 YGC 的时候,它们将存活的对象复制到未使用的 Survivor 空间( s0 或 s 1 ),然后将当前正在使用的空间完全清除,交换两块空间的使用状态。每次交换时,对象 的年龄会加 +1 。 如果 YGC 要移送的对象大于 Survivor 区容量的上限,则直接移交给老年代。一个 对象也不可能永远呆在新生代,在 JVM 中 一个对象从新生代晋升到老年代的阈值默认值 是 15 ,可以在 Survivor 区交换 14 次之后,晋升至老年代。

        堆区最容易出现的就是 OutOfMemoryError 错误,这种错误的表现形式会有以下两 种: 1 OutOfMemoryError: GC Overhead Limit Exceeded : 当 JVM 花太多时间执行垃 圾回收,并且只能回收很少的堆空间时,就会发生此错误。 2 OutOfMemoryError: Java heap space :假如在创建新的对象时, 堆内存中的空间不 足以存放新创建的对象, 就会引发此错误。 此种情况,与配置的最大堆内存有关,且受制于物理内存大小 。

 

  • 26
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值