在 Java 面试中,有一个几乎必问的问题:

Java GC 是怎么工作的?

很多人会回答:

  • GC 就是垃圾回收
  • JVM 会自动释放不用的对象

这样的回答 过于表面,面试官真正想听的是:

  • JVM 如何判断对象是垃圾
  • GC 的核心算法
  • 分代回收机制
  • 常见 GC 收集器

如果你能够把 GC 原理 + 分代机制 + 算法思想讲清楚,基本上 JVM 相关面试就能拿高分。

本文就从 底层原理 + 实战示例,带你彻底搞懂 Java GC。


Java面试题


一、问题背景

在 C/C++ 语言中,内存需要程序员手动管理:

int* p = new int;
delete p;

如果忘记释放,就会导致:

  • 内存泄漏
  • 程序崩溃

而 Java 的设计目标之一就是:

自动内存管理(Automatic Memory Management)

Java 通过 GC(Garbage Collection)垃圾回收机制,自动回收不再使用的对象。

也就是说:

User user = new User();
user = null;

当对象不再被引用时,JVM 会自动回收内存。

但这里有一个关键问题:

JVM 如何判断一个对象已经“死亡”?

这正是 GC 的核心原理。

如果你正在准备 JVM 面试题,我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1


二、技术原理解析

Java GC 的核心可以分为 三个关键部分

  1. 如何判断对象是否存活
  2. 垃圾回收算法
  3. 分代回收机制

我们逐一分析。


1 如何判断对象是否存活

JVM 主要使用 可达性分析算法(Reachability Analysis)

简单来说:

从一组 GC Roots 出发,查找所有可达对象。

如果对象 不可达,就会被判定为垃圾。

示意结构:

GC Roots
   │
   ├── Object A
   │      └── Object B
   │
   └── Object C

如果某个对象没有任何引用链连接到 GC Roots:

Object D

那么它就是 垃圾对象


什么是 GC Roots

GC Roots 主要包括:

  • 虚拟机栈中的引用对象
  • 方法区静态变量
  • 常量引用
  • JNI 引用

例如:

public class Test {

    private static Object obj = new Object();

    public static void main(String[] args) {

        Object a = new Object();

    }

}

这里的 GC Roots 包括:

  • main 方法栈变量 a
  • 静态变量 obj

2 垃圾回收算法

GC 的核心算法主要有三种。


标记清除算法(Mark-Sweep)

工作流程:

1 标记所有存活对象
2 清除未标记对象

示意:

对象1 ✓
对象2 ✓
对象3 ×
对象4 ×

清除对象3、对象4。

优点:

  • 实现简单

缺点:

  • 产生内存碎片

复制算法(Copying)

复制算法把内存分为两块:

From 区
To 区

流程:

1 标记存活对象
2 复制到另一块内存
3 清空旧空间

示意:

From: A B C D
To:   A B

优点:

  • 没有内存碎片

缺点:

  • 空间利用率低

标记整理算法(Mark-Compact)

流程:

1 标记存活对象
2 移动对象
3 清理垃圾

示意:

原始:
A × B × C

整理后:
A B C

优点:

  • 无碎片
  • 空间利用率高

缺点:

  • 移动对象成本较高

3 分代垃圾回收机制

Java GC 采用 分代回收思想

核心理念:

不同生命周期的对象使用不同回收策略

JVM 内存结构:

堆内存
 ├─ 新生代
 │   ├─ Eden
 │   ├─ Survivor0
 │   └─ Survivor1
 │
 └─ 老年代

对象创建流程:

对象创建 → Eden
Minor GC → Survivor
多次存活 → Old

也就是说:

  • 新生代对象生命周期短
  • 老年代对象生命周期长

因此:

区域 GC类型
新生代 Minor GC
老年代 Full GC

Minor GC:

  • 速度快
  • 频繁发生

Full GC:

  • 速度慢
  • 影响性能

如果你正在系统复习 JVM 面试知识,我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1


三、代码示例

下面通过代码简单模拟 GC 行为。


示例代码

public class GCDemo {

    public static void main(String[] args) {

        for(int i = 0; i < 1000000; i++){
            User user = new User();
        }

    }

}

class User{

    private byte[] data = new byte[1024];

}

运行过程:

1 创建大量对象
2 Eden 区被占满
3 触发 Minor GC

JVM 会:

标记存活对象
复制到 Survivor
清理 Eden

手动触发 GC

Java 可以通过以下方式建议 JVM 执行 GC:

System.gc();

示例:

public class TestGC {

    public static void main(String[] args) {

        Object obj = new Object();

        obj = null;

        System.gc();

    }

}

注意:

System.gc() 只是 建议 JVM 执行 GC,并不保证立即执行。


四、实际应用场景

GC 不只是面试知识,在实际开发中也非常重要。


1 JVM 调优

在高并发系统中,需要关注:

  • GC 次数
  • GC 时间
  • Full GC 频率

常见工具:

jstat
jmap
jvisualvm
arthas

2 高并发系统优化

如果出现:

Full GC 频繁

可能原因:

  • 老年代内存不足
  • 大对象过多
  • 内存泄漏

解决方案:

  • 调整堆大小
  • 优化对象创建
  • 使用对象池

3 大型框架运行

很多框架会产生大量对象:

  • Spring
  • Netty
  • MyBatis

如果 GC 不合理,可能出现:

STW (Stop The World)

导致系统 短暂卡顿


Java面试题


如果你准备 Java 面试,建议重点掌握:

  • JVM 内存结构
  • GC 算法
  • 分代回收机制
  • 常见垃圾收集器

我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1

包含:

  • Java核心
  • JVM原理
  • 并发编程
  • Spring
  • MySQL
  • Redis
  • 微服务架构

五、总结

最后总结一下 Java GC 的核心知识点。

1 GC 的作用

自动回收不再使用的对象,避免内存泄漏。


2 判断对象是否存活

使用 可达性分析算法

GC Roots → 引用链 → 对象

不可达对象会被回收。


3 三种核心 GC 算法

算法 特点
标记清除 简单但有碎片
复制算法 无碎片但空间浪费
标记整理 无碎片但移动成本高

4 分代回收机制

新生代 → Minor GC
老年代 → Full GC

新生代对象生命周期短,回收频繁。


5 面试标准回答

如果面试官问:

Java GC 的工作原理是什么?

可以回答:

Java GC 通过可达性分析算法判断对象是否存活,然后使用标记清除、复制算法、标记整理等算法回收垃圾对象。JVM 采用分代回收机制,将堆分为新生代和老年代,不同区域使用不同回收策略,从而提高垃圾回收效率。


关注我,持续更新Java面试核心知识。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐