Skip to content

对象生命周期:从 new 到回收

对象生命周期把堆、栈、类加载、对象头、引用链和 GC 串在一起。理解这条链路后,堆 OOM、Full GC、对象晋升、大对象、ThreadLocal 泄漏和缓存问题会更容易定位。

总链路

text
new 指令
  -> 类加载检查
  -> 分配内存
  -> 初始化对象头
  -> 执行构造方法
  -> 被引用持有
  -> 参与 GC Roots 可达性分析
  -> 存活 / 移动 / 晋升 / 回收

类加载检查

执行 new 前,JVM 要确认目标类已经被加载、链接和初始化。如果类还没准备好,会触发类加载流程。

这就是为什么第一次创建某个类的对象可能比后续更慢:它可能包含类加载、验证、初始化、静态块执行和 JIT 预热。

内存分配

对象通常分配在堆里。常见方式:

方式说明
指针碰撞空闲空间连续时,移动指针即可分配
空闲列表空闲空间不连续时,从列表中找可用块
TLAB每个线程预分配一小块 Eden,减少多线程分配竞争

TLAB(Thread Local Allocation Buffer)让多数小对象分配非常快。对象分配并不总是昂贵,真正昂贵的是大量对象存活、晋升或造成 GC 压力。

对象头

HotSpot 对象通常包含:

部分说明
Mark Word哈希、锁状态、GC 年龄等
Klass Pointer指向类元数据
Array Length数组对象才有
实例数据字段值
对齐填充满足内存对齐

所以对象大小不等于字段大小。引用压缩、字段排列、对象头、数组头和对齐都会影响实际内存。

构造方法

对象内存分配后,JVM 会执行初始化逻辑:

text
默认零值 -> 字段初始化 -> 构造代码块 -> 构造方法

构造方法里如果把 this 暴露给其他线程,可能出现对象尚未完全初始化就被访问的并发问题。

引用链

对象是否能回收,关键看是否可达:

text
GC Roots -> 引用 -> 引用 -> 目标对象

常见让对象长期存活的引用:

  • 静态集合。
  • 本地缓存。
  • ThreadLocal。
  • 线程池任务队列。
  • 监听器、回调、订阅关系。
  • 类加载器。
  • JNI 引用。

内存泄漏的本质不是“没有 free”,而是“不该继续被引用的对象仍然可达”。

年轻代、老年代和晋升

传统分代理解仍然有用:

text
Eden -> Survivor -> Old

常见过程:

  1. 新对象进入 Eden。
  2. Young GC 后仍存活的对象进入 Survivor。
  3. 对象年龄增加。
  4. 达到阈值或 Survivor 放不下时晋升到 Old。
  5. 老年代压力过大时触发 Mixed GC 或 Full GC。

G1、ZGC 等回收器内部模型不同,但仍然围绕对象生命周期、存活率和回收收益做判断。

大对象

大对象可能直接进入老年代,或者在 G1 中成为 Humongous 对象。

常见来源:

  • 大数组。
  • 大字符串。
  • 大 JSON。
  • 一次性读取完整文件。
  • 批量查询结果。
  • 图片、二进制内容。

优化方向:

  • 分块处理。
  • 流式读取。
  • 限制单批大小。
  • 避免长期缓存大对象。
  • 对外部内容使用对象存储或临时文件。

ThreadLocal 泄漏

ThreadLocal 典型引用关系:

text
Thread -> ThreadLocalMap -> Entry -> value

在线程池中,线程长期存活。如果业务没有及时 remove(),value 也可能长期存活。

建议:

java
try {
    CONTEXT.set(value);
    // business
} finally {
    CONTEXT.remove();
}

从对象生命周期排查 OOM

  1. 看 GC 日志确认是堆、元空间、直接内存还是容器 OOM。
  2. 如果是堆,抓 heap dump。
  3. 看最大对象和最多对象。
  4. 找 GC Roots 引用链。
  5. 判断是容量不足、峰值流量、缓存无界、队列积压还是泄漏。
  6. 先修生命周期和上限,再考虑调大堆。

常见误区

误区更准确的理解
对象创建一定慢TLAB 下小对象分配很快,问题通常在存活和回收
OOM 就是堆太小可能是泄漏、直接内存、元空间、线程栈或容器限制
Full GC 能解决泄漏可达对象不会被 GC 回收
缓存越大越好缓存必须有容量上限、过期策略和监控
heap dump 一定能看到全部内存直接内存、native、线程栈不完整体现在 heap dump 中
别急,先让缓存热一下。