Java对象生命周期始于堆内存分配、终于垃圾回收;引用变量存于栈中,仅保存指向堆中对象的地址,对象实例(含对象头、实例数据、对齐填充)才真正分配在堆中。

Java对象的生命周期始于堆内存分配,终于垃圾回收;而引用类型本身并不在堆中分配,它只是栈中保存的一个地址值,指向堆里的实际对象。真正分配在堆中的,是对象实例(包括对象头、实例数据和对齐填充),不是引用变量。
对象创建时的堆内存分配流程
执行 new MyClass() 时,JVM 在堆中完成以下关键步骤:
-
类检查与加载:先确认
MyClass已完成加载、链接和初始化; - 内存分配:在堆中划分一块连续空间(通过指针碰撞或空闲列表),大小由类结构在编译期确定;
-
零值初始化:将分配区域除对象头外全部置为默认值(
int→0、Object→null等); - 设置对象头:写入 Mark Word(含哈希码、GC年龄、锁状态)和 Klass Pointer(指向类元数据);
-
调用构造方法:执行
<init>方法,完成字段显式赋值、代码块、构造器逻辑; -
返回引用:把堆中对象起始地址赋给栈中的引用变量(如
MyClass obj)。
引用变量的存储位置与本质
引用变量(如 obj)本身不存于堆中,而是存储在栈帧里(局部变量)或方法区/堆中(静态字段、成员变量)。它的作用是保存一个内存地址,这个地址指向堆中某个对象的起始位置。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 多个引用可指向同一堆对象,修改对象状态会相互可见;
- 引用类型(
String、List等)的变量,其值就是这个地址,不是对象本身; - 基本类型变量(
int、boolean)直接存值,不涉及堆引用。
不同引用类型对对象生命周期的影响
是否被回收,取决于对象是否可达——即是否存在一条从 GC Roots 出发、经由强引用链能到达该对象的路径。引用类型决定了这条链的“强度”:
立即学习“Java免费学习笔记(深入)”;
-
强引用(最常见):如
MyClass obj = new MyClass();,只要 obj 存在且未置 null,对象不会被回收; - 软引用:内存不足时才回收,适合缓存场景;
-
弱引用:下次 GC 就可能回收,常用于避免内存泄漏(如
WeakHashMap); - 虚引用:仅用于跟踪对象被回收的时机,必须配合引用队列使用。
TLAB 与堆分配优化细节
为减少多线程竞争,JVM 默认启用 TLAB(Thread Local Allocation Buffer):
- 每个线程拥有独立的小块堆内存,对象优先在 TLAB 中分配;
- TLAB 耗尽时,再在共享堆中分配(可能触发同步机制如 CAS);
- 大对象或 TLAB 不适配时,直接在 Eden 区分配;
- 对象分配失败且无法扩容时,可能触发 Minor GC。

















