java对象在堆内存(Heap Space)的内存分配

java对象在堆内存(Heap Space)的内存分配

在这里插入图片描述

Eden区和Survivor区是新生代、Tentured区是老年代

对象优先在 Eden 区分配

多数情况,对象都在新生代 Eden 区分配。当 Eden 区分配没有足够的空间进行分配时,虚拟机将会发起一次 Minor GC。

大对象直接进入老年代

所谓大对象是指需要大量连续内存空间的对象(如大数组),频繁出现大对象是致命的,会导致在内存还有不少空间的情况下提前触发 GC 以获取足够的连续空间来安置新对象。

原因:在新生代使用的是标记-清除算法来处理垃圾回收的情况下,如果大对象直接在新生代分配就会导致 Eden 区和两个 Survivor 区之间发生大量的内存复制。因此对于大对象都会直接在老年代进行分配。

长期存活对象将进入老年代

当我们实例化一个对象的时候,对象 = 对象头 + 对象实例数据(instance data) + 对齐填充(padding),对象头 =
对象运行时数据(mark word 8个字节) + 对象类型指针(class pointer 由8个字节压缩为4个字节)+
(如果是数组就还需要4个字节)。

在对象头的对象运行时数据里面有4bit用来存放对象的年龄,对象初始年龄为 0。对象在新生代中每熬过一次 Minor GC 年龄就加 1,当年龄达到一定程度就会被晋升到老年代。(默认 15,可通过-XX:MaxTenuringThreshold进行设置)

动态对象分配

当幸存区(Survivor )中同一年龄的对象大于一半内存的时候,大于等于该年龄的对象会被晋升到老年代

类加载完成,确定分配在哪一个区后,根据内存是否规整,有两种内存分配方式:

  • 指针碰撞:如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离,这样便完成分配内存工作。
  • 空闲列表:如果Java堆的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。
    选择哪种分配方式是由 Java 堆是否规整来决定的,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当你遇到`java.lang.OutOfMemoryError: Java heap space`错误时,意味着你的Java堆内存不足以支持程序的运行。要排查使用堆内存最多的部分,你可以按照以下步骤进行: 1. 使用堆内存分析工具:使用一些堆内存分析工具,比如Eclipse Memory Analyzer(MAT)或Java VisualVM等,可以帮助你分析程序在运行时的堆内存使用情况。这些工具可以显示内存快照和对象引用关系,帮助你找出占用大量堆内存对象和代码。 2. 检查内存泄漏:内存泄漏是指无用对象仍然被保留在内存中,导致内存占用不断增加。使用堆内存分析工具可以帮助你检查是否存在内存泄漏问题。查看内存快照中的对象引用关系,找出无用对象并分析它们的引用路径,判断是否有对象被意外保留。 3. 检查大对象:大对象是指占用大量堆内存空间的对象。使用堆内存分析工具可以查看对象的大小,识别占用最多内存的大对象。检查这些大对象是否能够进行优化或重构,减少其对堆内存的需求。 4. 检查集合和缓存:集合和缓存是常见的内存消耗点。检查你的代码中使用的集合和缓存对象,确保它们被正确地清理或释放。避免在集合中存储大量数据或长时间保留不必要的缓存。 5. 调整堆内存大小:如果经过以上步骤检查后还是无法解决问题,你可以尝试调整Java堆内存的大小。通过修改JVM启动参数中的-Xmx和-Xms参数来增加或减少堆内存的分配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值