JVM 分代空间工作流程:从对象创建到垃圾回收的全生命周期

JVM 分代空间工作流程:对象从创建到回收的完整生命周期

这是 JVM 最核心、面试必问、线上调优必须吃透的全流程闭环 ,我用最清晰、一步不丢的方式给你整理出来,看完就能彻底理解。


一、先记住:JVM 堆的标准分代结构

plaintext

复制代码
堆 Heap
├─ 年轻代 Young Gen(1/3)
│   ├─ Eden 伊甸区    (80%)
│   ├─ S0 幸存者区0   (10%)
│   └─ S1 幸存者区1   (10%)
│
└─ 老年代 Old Gen(2/3)

固定规则:

  • S0 和 S1 永远只有一个有数据,另一个必须空
  • 新对象 → Eden
  • 活很久的对象 → 老年代

二、完整版流程:对象从出生到死亡(一步一步)

第 1 步:对象诞生 ------ 分配在 Eden 区

  • 所有新对象 优先在 Eden 区分配内存
  • Eden 区很小,很快就会被填满
  • 此时对象 = 新生对象

java

运行

复制代码
User user = new User(); // 直接进 Eden

第 2 步:Eden 满 → 触发 Minor GC(年轻代 GC)

当 Eden 区没有空间分配新对象时:

  1. 触发 Minor GC
  2. STW(Stop The World) 暂停所有业务线程
  3. 扫描 Eden + 正在使用的 Survivor 区
  4. 存活对象 标记,垃圾对象 直接清除

特点

  • Minor GC 极快
  • 发生频率非常高
  • 只回收年轻代

第 3 步:存活对象复制 → 空的 Survivor 区

Minor GC 后:

  1. Eden 清空
  2. 存活对象 → 复制空的 Survivor 区(S0 或 S1)
  3. 对象年龄 +1

关键规则

  • S0 和 S1 必须交替使用
  • 一次 GC 后:一个空、一个存数据
  • 这种机制叫 复制算法,无内存碎片

第 4 步:对象在 Survivor 区来回 "轮换"

每触发一次 Minor GC:

  • 存活对象 从当前 S 区 → 复制到另一个空 S 区
  • 年龄 +1
  • 原来的 S 区 清空

对象就在 S0 ↔ S1 之间来回移动。


第 5 步:年龄达标 → 晋升老年代

当对象年龄达到 阈值(默认 15)

  • 直接进入 老年代
  • 不再参与 Survivor 轮换

晋升老年代的 4 种条件(必背)

  1. 年龄达到 15 (默认,可通过 -XX:MaxTenuringThreshold 设置)
  2. 大对象(大数组、长字符串)直接进入老年代
  3. Survivor 区 相同年龄的对象总大小 > Survivor 空间一半
  4. Minor GC 后存活对象 太多,放不进 Survivor

第 6 步:老年代空间不足 → Major GC / Full GC

老年代存放长期存活对象,一旦满了:

  1. 触发 Major GC / Full GC
  2. STW 时间变长(比 Minor GC 慢 10 倍以上)
  3. 回收整个堆:年轻代 + 老年代 + 元空间

重点

Full GC 是线上卡顿、CPU 高、服务雪崩的头号元凶!


第 7 步:老年代存活对象最终被回收

  • 老年代的对象如果长期没有引用
  • 在 Full GC 时被回收
  • 对象生命周期正式结束

三、一张图看懂完整生命周期(最强总结)

plaintext

复制代码
新对象
   ↓
Eden 区分配
   ↓
Eden 满 → Minor GC
   ↓
存活对象 → S0 / S1(年龄+1)
   ↓
S0 ↔ S1 轮换(每次GC年龄+1)
   ↓
年龄达标 / 大对象 / Survivor 空间不足
   ↓
晋升老年代
   ↓
老年代满 → Full GC
   ↓
对象被回收 / 永久存活

四、核心关键词(面试直接背)

  • Eden:新对象出生地
  • Minor GC:回收年轻代,速度快
  • Survivor:对象轮换区,无碎片
  • 年龄:决定对象何时进入老年代
  • 老年代:存长期存活对象
  • Full GC:慢、卡顿、线上大忌
  • 复制算法:年轻代使用,无碎片
  • 标记整理 / 标记清除:老年代使用

五、高频面试题(标准答案)

1. 对象从创建到回收经历了哪些区域?

Eden → S0 → S1 → 老年代 → 被 GC 回收

2. 对象什么时候进入老年代?

年龄 15、大对象、Survivor 空间不足、年龄动态判断。

3. 为什么需要 Survivor 区?

避免对象过早进入老年代,减少 Full GC。

4. Minor GC 和 Full GC 区别?

  • Minor GC:年轻代、快、频繁
  • Full GC:全堆、慢、卡顿、少发生

5. 为什么分代?

不同对象生命周期不同,分代可以让 GC 效率最高。


总结

JVM 分代工作流程 = 对象出生 → 年轻代轮换 → 晋升老年代 → 最终回收 整个流程围绕 Eden → Survivor → Old 展开,是理解 GC、OOM、JVM 调优的基础。

相关推荐
2401_873544922 小时前
使用XGBoost赢得Kaggle比赛
jvm·数据库·python
m0_569881472 小时前
进阶技巧与底层原理
jvm·数据库·python
2501_945423543 小时前
数据分析师的Python工具箱
jvm·数据库·python
czlczl200209253 小时前
JVM类加载机制
jvm
2401_879693873 小时前
自动化与脚本
jvm·数据库·python
小王不爱笑1323 小时前
深入浅出 JVM:从内存结构到性能调优的全维度解析
jvm
xushichao19894 小时前
Python Web爬虫入门:使用Requests和BeautifulSoup
jvm·数据库·python
qq_416018724 小时前
开发一个简单的Python计算器
jvm·数据库·python