java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java垃圾回收GC全解

Java垃圾回收(GC)核心原理与面试完全讲解

作者:吾好梦中写代码

Java的垃圾回收(GC)是Java虚拟机(JVM)自动管理内存的核心机制,良好的GC调优可以显著提升应用性能,减少停顿时间,这篇文章主要介绍了Java垃圾回收(GC)核心原理与面试的相关资料,需要的朋友可以参考下

前言

本文整合GC 机制、回收算法、收集器选择、OOM / 内存泄漏、FullGC、GC Roots全套核心知识,适合 Java 调优入门、面试背诵、线上问题排查。

一、什么是垃圾回收(GC)

JVM 自动清理堆内存中不再使用的对象,释放内存空间,避免内存泄漏和 OOM 的自动化机制。不需要手动管理内存,由 GC 线程自动完成。

GC 核心三问:

  1. 哪些对象是垃圾?
  2. 怎么回收垃圾?
  3. 什么时候回收?

二、如何判断对象是垃圾?

1. 引用计数法(不用)

2. 可达性分析算法(HotSpot 真正使用)

GC Roots 固定 4 类

  1. 虚拟机栈中引用的对象(局部变量、方法参数)
  2. 本地方法栈引用的对象
  3. 方法区静态变量引用的对象
  4. 方法区常量引用的对象

口诀:栈、静、常、本

三、垃圾回收三大算法

1. 标记 - 清除

2. 标记-复制(新生代专用)

它将内存空间划分为两块,每次只使用其中一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后清理掉这一块。

3. 标记 - 整理(老年代专用)

它不再划分内存空间,而是将存活的对象向内存的一端移动,然后清理边界以外的内存。

四、分代回收机制(JVM 最核心)

Java 堆 = 新生代 + 老年代不同年代对象生命周期不同 → 使用不同回收策略。

1. 新生代(对象朝生夕死)

2. 老年代(对象存活时间长)

3. 为什么 Minor GC 偏爱标记-复制?

这主要取决于新生代对象的存活特征

4. Minor GC 如何利用标记-复制算法?

在 HotSpot 虚拟机中,新生代被划分为三个区域:Eden 区 和两个 Survivor 区(From 和 To)。默认比例通常是 8:1:1。

Minor GC 的执行流程完美诠释了标记-复制算法:

  1. 对象分配:新对象优先在 Eden 区分配。
  2. 触发 GC:当 Eden 区满了,触发 Minor GC。
  3. 标记与复制:
    • JVM 扫描 Eden 区和 From 区(当前存放存活对象的 Survivor 区),标记出所有存活的对象。
    • 将这些存活的对象复制到 To 区(当前是空的 Survivor 区)。
    • 在这个过程中,对象的年龄(Age)会 +1。
  4. 清理与交换:
    • 直接清空 Eden 区和 From 区(因为存活对象都搬走了)。
    • 交换指针:将 From 和 To 的角色互换。原来的 To 区变成新的 From 区(存放存活对象),原来的 From 区变成新的 To 区(变为空,等待下一次 GC)。

5. 关键细节:晋升机制

在 Minor GC 的标记-复制过程中,如果 To 区空间不足(比如存活对象太多),或者对象年龄达到了阈值(默认 15 岁),这些对象就不会被复制到 To 区,而是直接晋升到老年代。

五、完整 GC 执行流程

  1. 新对象优先进入 Eden 区
  2. Eden 满 → Minor GC
  3. 存活对象进入 S0
  4. 再次 GC → 对象在 S0 ↔ S1 来回复制
  5. 年龄达到阈值(默认 15)→ 晋升老年代
  6. 老年代满 → Full GC

六、Full GC 是什么?为什么可怕?

定义

Full GC = 全堆垃圾回收回收:新生代 + 老年代 + 元空间

Full GC 会从 GC Root 出发,标记所有可达对象。新生代使用复制算法,清空 Eden 区。老年代使用标记-整理算法,回收对象并消除碎片。

触发条件(5 个)

  1. 老年代空间不足
  2. 元空间不足
  3. Minor GC 后晋升失败: 在进行 Young GC 的时候,如果发现老年代可用的连续内存空间 < 新生代历次 Young GC 后升入老年代的对象总和的平均大小,说明本次 Young GC 后升入老年代的对象大小,可能超过了老年代当前可用的内存空间,就会触发 Full GC。
  4. 显式调用 System.gc()
  5. 并发收集器失败(CMS/G1)

危害

STW 时间最长,系统卡顿、接口超时、雪崩生产环境必须尽量避免。

七、内存泄漏 vs 内存溢出(OOM)

1. 内存泄漏

短生命周期对象,被长生命周期对象持有引用,导致 GC 无法回收。该死的对象死不掉 → 慢慢占满内存。

典型场景(原因):

2. 内存溢出 OOM

内存彻底耗尽,GC 后仍无法分配新对象 → 程序崩溃。

常见 OOM:

3.内存泄漏解决方法

八、垃圾收集器如何选择?

垃圾回收器的核心作用是自动管理 Java 应用程序的运行时内存。它负责识别哪些内存是不再被应用程序使用的,并释放这些内存以便重新使用。

核心原则:

没有最好,只有最适合:吞吐量 / 延迟

根据业务要求选择

1. Parallel GC(JDK8 默认)

2. CMS

特点:

CMS 使用标记-清除算法进行垃圾收集,分 4 大步:

重新标记和三色标记法:

虽然重新标记也需要停顿,但它只处理变动过的对象,比全量扫描要快得多,这就是 CMS 的精髓所在。

3. G1(90% 生产首选)

G1 把 Java 堆划分为多个大小相等的独立区域 Region,每个区域都可以扮演新生代或老年代的角色。同时,G1 还有一个专门为大对象设计的 Region,叫 Humongous 区。这种区域化的管理使得 G1 可以更灵活地进行垃圾收集,只回收部分区域而不是整个新生代或老年代。

特点:

G1 收集器的运行过程大致可划分为这几个步骤:

因为只清理少数几个 Region,而不是整个堆。所以 STW 的时间很短。

4. ZGC(超低延迟)

总结:通用选 G1,计算选 Parallel,低延迟选 ZGC

九、标记阶段一定 STW 吗?(高频面试题)

不是!

十、OOM 排查标准流程

  1. 看日志:确定 OOM 类型
  2. 加 JVM 参数生成 dump
  3. 使用 MAT/JVisualVM 分析堆快照
  4. 定位大对象、引用链、内存泄漏
  5. 修复代码 + 调优 JVM

一、补充 1:四种引用类型

JVM 不只有强引用,还有 4 种,决定对象会不会被 GC 回收:

  1. 强引用(Strong)Object obj = new Object();只要存在,永远不会被 GC 回收(内存泄漏根源)

  2. 软引用(Soft)内存不足时才回收适合:缓存

  3. 弱引用(Weak)下次 GC 直接回收适合:防止内存泄漏

  4. 虚引用(Phantom)任何时候都可以被回收,等同于没有引用,用来管理堆外内存

二、补充 2:对象晋升老年代的 4 个规则(调优核心)

  1. 年龄达标(默认 15 岁)
  2. 动态年龄判断S 区相同年龄对象大小 > S 区一半 → 直接进老年代
  3. 大对象直接进老年代可通过 -XX:PretenureSizeThreshold 设置
  4. Minor GC 后存活对象太大 → S 区放不下 → 直接进老年代

三、补充 3:STW(Stop The World)

哪些操作会触发STW?

1. 垃圾回收(最主要)

2. 堆内存分配担保(晋升失败)

3. 显式调用 System.gc ()

4. 堆内存压缩

注意:只要 GC,一定有 STW,只是时间长短不同!

调优目标:降低 STW 次数 + 缩短 STW 时间

如何减少STW时间?(调优)

1. 选用低延迟收集器

2. 优化对象生命周期

3. 控制堆内存大小

4. 避免 Full GC

四、补充 4:并发标记的问题(漏标)

为什么 CMS/G1 需要 重新标记 (Remark)?因为并发标记时,用户线程还在跑,会导致:

五、补充 5:内存碎片(调优踩坑最多)

内存碎片 → 空间足够但无法分配 → OOM

六、补充 6:安全点 & 安全区域(GC 底层)

GC 不是想停就能停,必须跑到安全点才会 STW:

GC 会等待所有线程进入安全点,才开始回收。

七、补充 7:GC 日志关键指标(调优必看)

你后面调优一定会看 GC 日志,重点看 4 个指标:

  1. YGC 次数
  2. YGC 耗时
  3. FGC 次数
  4. FGC 耗时

好的 GC 状态:

八、补充 8:JDK 17 + G1/ZGC 核心变化

  1. G1 是 JDK 9~17 默认 GC
  2. ZGC 支持分代、超大堆、亚毫秒停顿
  3. CMS 完全被移除
  4. 元空间简化,不再容易溢出
  5. 增强并发能力,GC 效率大幅提升

基本上这就是完整版的 GC 知识体系,后面就是调优的实战 ,一般在面试中的形式便是结合项目的场景题。

总结

到此这篇关于Java垃圾回收(GC)核心原理与面试完全讲解的文章就介绍到这了,更多相关Java垃圾回收GC全解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文