MST

星途 面试题库

面试题:Java中JVM内存分配策略之堆内存分配

请简述Java JVM堆内存的主要分配策略,以及对象在堆内存中分配的大致流程。
16.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

Java JVM堆内存主要分配策略

  1. 指针碰撞(Bump the Pointer)
    • 适用场景:当堆内存空间是规整的,即已使用的内存和未使用的内存分别在两端,中间由一个指针分隔开。这种情况通常出现在使用Serial、ParNew等采用标记 - 整理算法的垃圾回收器时。
    • 分配过程:分配内存时,只需要将指针向未使用内存方向移动与对象大小相等的距离即可,就像碰撞指针一样,所以叫指针碰撞。
  2. 空闲列表(Free List)
    • 适用场景:当堆内存空间不规整,已使用的内存和未使用的内存相互交错时,垃圾回收器(如CMS)无法简单地通过指针碰撞来分配内存。此时就需要维护一个空闲列表,记录哪些内存块是可用的。
    • 分配过程:当对象需要分配内存时,从空闲列表中找到一块足够大的内存块来分配给对象,并更新空闲列表。

对象在堆内存中分配的大致流程

  1. 对象优先在Eden区分配
    • 当Java程序创建一个新对象时,大多数情况下,对象首先会尝试在新生代的Eden区分配内存。Eden区是新生代中较大的一块内存区域,用于存放新创建的对象。
  2. Eden区空间不足时
    • 如果Eden区空间不足,会触发Minor GC(新生代垃圾回收)。在Minor GC过程中,垃圾回收器会扫描Eden区和From Survivor区(Survivor区分为From和To两个区域),标记出存活的对象,并将存活对象复制到To Survivor区,同时清理Eden区和From Survivor区中不再使用的对象所占用的内存空间。
    • 经过一次Minor GC后,如果To Survivor区能够容纳存活对象,那么存活对象将在To Survivor区中存储。并且这些对象的年龄(对象在Survivor区中经历的垃圾回收次数)会加1。
  3. 对象晋升到老年代
    • 当对象的年龄达到一定阈值(默认是15,可通过参数 -XX:MaxTenuringThreshold 调整)时,该对象会被晋升到老年代。另外,如果在Minor GC后,To Survivor区无法容纳存活对象,那么这些存活对象也会直接晋升到老年代。
    • 老年代用于存放生命周期较长的对象,当老年代空间不足时,会触发Full GC(全量垃圾回收),垃圾回收器会对整个堆(包括新生代和老年代)进行垃圾回收,以释放空间。