Skip to Content
面试题库Jvm[面试题] JVM有哪些垃圾回收算法?

[面试题] JVM有哪些垃圾回收算法?

📖 版块 A:知识讲解版 (温故知新)

  • 标记-清除算法 (Mark-Sweep)

    • 过程:分为“标记”和“清除”两个阶段。首先标记出所有需要回收的对象,标记完成后统一回收掉所有被标记的对象。
    • 缺点:效率不稳定(对象多时标记慢);产生大量不连续的内存碎片,导致大对象无法分配内存。
  • 标记-复制算法 (Copying)

    • 过程:将内存分为大小相等的两块,每次只使用其中一块。当这一块内存用完时,将还存活的对象复制到另一块上面,然后把已使用过的内存空间一次清理掉。
    • 优点:实现简单,运行高效,无碎片。
    • 缺点:内存利用率低(浪费了一半空间)。现代 JVM 常用 Eden:Survivor = 8:1:1 的比例来优化。
  • 标记-整理算法 (Mark-Compact)

    • 过程:标记阶段与“标记-清除”一样,但后续步骤是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。
    • 优点:解决了空间碎片问题,且不需要浪费一半内存。
    • 缺点:移动存活对象并更新引用地址是一项沉重的工作,会带来较长的 Stop The World (STW)。
  • 分代收集理论 (Generational Collection)

    • 核心思想:根据对象存活周期的不同将内存分为几块(新生代、老年代)。
    • 应用:新生代对象“朝生夕死”,适合用“复制算法”;老年代对象存活率高,适合用“标记-清除”或“标记-整理”。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:JVM 有哪些垃圾回收算法?

💬 高手逐字稿

JVM 的垃圾回收算法并不是孤立存在的,它们的设计核心是围绕着“分代收集理论”展开的。目前主流的算法主要有三种:标记-清除、标记-复制以及标记-整理。

首先是标记-清除算法。它是最基础的算法,分为标记存活对象和清除未标记对象两个阶段。它的主要问题是会产生大量的内存碎片。如果碎片过多,后续分配大对象时即便总空间够,也会因为找不到连续空间而频繁触发 Full GC。所以现在的收集器很少单独使用它,通常是作为其他算法的补充。

其次是标记-复制算法。为了解决碎片和效率问题,它将内存分为两块,只把存活对象拷贝到另一半。这种算法在“新生代”里效率极高,因为新生代 90% 以上的对象都是朝生夕死的,拷贝量很小。虽然它有空间浪费的问题,但现在的 HotSpot 虚拟机通过把新生代划分为 Eden 和两个 Survivor 区,把空间浪费降低到了 10%。

最后是标记-整理算法。它主要针对“老年代”设计的。老年代对象存活率高,不适合复制。它在标记之后,会让所有存活对象向内存的一端移动,然后清理掉边界外的内存。这样既解决了碎片问题,又不用浪费一半内存。但代价是,移动对象并修改引用地址是一个非常耗时的操作,会增加 STW(Stop The World)的时间。

这里有一个容易被忽略的细节:到底该不该移动对象?

这是一个性能权衡的��题。如果移动对象(如标记-整理),虽然回收时 STW 变长,但因为内存规整,后续分配对象速度极快;如果不移动对象(如标记-清除),回收虽然快,但分配内存时需要维护“空闲列表”,且会有碎片。

比如 CMS 收集器,它追求低延迟,所以平时用标记-清除,只有当碎片多到无法分配时,才会退化到 Serial Old 使用标记-整理;而像吞吐量优先的 Parallel Scavenge 收集器,则直接基于标记-整理。最新的 G1 和 ZGC 则更加智能化,它们在局部使用复制算法,全局看更接近整理,通过这种方式在吞吐量和延迟之间达到一个极致的平衡。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册