java对象实例均存储在堆内存中,是线程共享区域;new创建对象时,jvm在堆中分配内存、初始化零值、设置对象头并执行构造方法;对象布局含对象头、实例数据和对齐填充;堆分新生代与老年代,影响对象分配与回收。

Java 中的对象实例都存储在堆内存(Heap)中,这是 JVM 管理的、所有线程共享的一块运行时内存区域。当你用 new 关键字创建对象(如 new String("hello") 或 new Person()),JVM 就会在堆中分配一块连续内存来存放该对象的实际数据。
堆内存如何为对象分配空间
当一个对象被创建时,JVM 会做几件事:
- 检查类是否已加载、解析和初始化(触发类加载机制)
- 在堆中划分一块足够大的内存空间(大小由对象的字段类型和数量决定)
- 将内存空间初始化为零值(不执行构造方法,但基本类型字段如
int默认为 0,boolean为false,引用类型为null) - 设置对象头(Object Header),包含哈希码、GC 分代年龄、锁状态标志、指向类元数据的指针等信息
- 执行构造函数(
<init></init>方法),给字段赋初始值,完成对象真正意义上的“诞生”
对象在堆中的布局结构
一个 Java 对象在堆中通常由三部分组成:
- 对象头(Header):包括 Mark Word(存储哈希码、锁信息、GC 标志等)和 Class Pointer(指向方法区中该对象所属类的元数据)
-
实例数据(Instance Data):真正存储对象字段的内容,按字段宽度从大到小排列(如
long/double→int/float→short/char→byte/boolean),父类字段排在子类前面,JVM 可能做字段重排序或填充(padding)以对齐内存(通常是 8 字节对齐) - 对齐填充(Padding):仅起占位作用,确保整个对象大小是 8 字节的整数倍,便于 CPU 高效读取
堆内存分代与对象生命周期
现代 JVM(如 HotSpot)将堆划分为不同代,影响对象的存储位置和回收方式:
- 新生代(Young Gen):新创建的对象首先分配在 Eden 区;经历一次 Minor GC 后仍存活的对象,会被移到 Survivor 区(S0/S1);多次幸存后晋升至老年代
- 老年代(Old Gen):存放长期存活的对象,比如缓存、全局配置、大对象(某些 JVM 对超过一定大小的对象直接分配到老年代)
- 元空间(Metaspace,不在堆中):注意,类的元数据(如类名、方法信息、常量池)存放在本地内存的元空间,不是堆的一部分;字符串常量池(JDK 7+)也移到了堆中,但静态变量引用的对象仍在堆上
栈中引用 vs 堆中对象
需要区分清楚的是:对象本身在堆中,而局部变量中的引用(reference)在虚拟机栈中。例如:
Person p = new Person();
其中 p 是一个引用变量,保存在当前线程的栈帧里,它的值是一个地址(或句柄,取决于 JVM 配置),指向堆中那个真实的 Person 实例。这个引用可能为 null,但它本身不是对象,也不占堆内存。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











