堆内存是Java内存管理的核心区域,一个JVM实例只存在一个堆内存,在JVM启动时被创建并确定空间大小。
堆内存主要组成部分:
1、堆顶(Young Generation):
这是一个存储新生成对象的内存区域。在HotSpot虚拟机中,堆顶通常又被细分为Eden区、Survivor区(通常有两个:S0和S1)。几乎所有的Java对象都是在Eden区被new出来的。 对象优先分配策略:当需要创建一个新的对象时,JVM会尝试在Eden区域进行分配。如果Eden区域没有足够的空间,JVM会触发一次垃圾回收,清理无用的对象,并将存活的对象移动到Survivor区域。 大对象直接进入老年代:当需要创建一个较大的对象时,为了避免在Eden区域和Survivor区域之间的复制操作,JVM会直接将它分配到老年代中。
2、年老代(Old Generation):
当堆顶达到容量上限时,部分对象会被转移至年老代。此外,如果一个对象经过多次垃圾回收后仍然存活,JVM会将其移动到老年代中。JVM通过给每个对象设置年龄计数器来判断对象的存活时间,当对象的年龄达到一定阈值时,会被移动到老年代中。
3、永久代(Permanent Generation,但在Java 8及以后的版本中,这部分被元空间(Metaspace)替代):
用于存放永久数据,如Java类、字段和方法。
堆内存的分配策略:
1、对象优先在Eden分配:
新创建的对象会优先在Eden区域进行分配。
2、大对象直接进入老年代:
避免在Eden区域和Survivor区域之间的复制操作。
3、长期存活的对象将进入老年代:
如果一个对象经过多次垃圾回收后仍然存活,它将被移动到老年代中。
栈内存用于存储方法的局部变量、方法的参数和方法的返回值。栈内存的分配和回收是由线程自动管理的,不需要垃圾回收器的介入。当方法调用结束时,栈帧会被立即回收,释放栈空间。
堆内存的大小可以通过JVM启动参数进行配置,如-Xms表示堆空间的起始内存,-Xmx表示堆空间的最大内存。合理地配置这些参数对于提高程序的性能和稳定性非常重要。