常见的【垃圾收集算法】

目录

      • [1. 标记 - 清除算法(Mark-Sweep)](#1. 标记 - 清除算法(Mark-Sweep))
      • [2. 复制算法(Copying)](#2. 复制算法(Copying))
      • [3. 标记 - 整理算法(Mark-Compact)](#3. 标记 - 整理算法(Mark-Compact))

1. 标记 - 清除算法(Mark-Sweep)

自己的理解:

标记清除算法:从GC root出发扫描,并标记所有存活的对象,之后清除没有标记的对象。

优点是:核心流程简单;

缺点是:导致内存碎片化严重(无法分配需要连续空间的大对象,例如数组)。在可回收的对象(垃圾对象)多时,大量的标记清除特别耗时(由于标记过程需要全堆遍历,会使得 GC 停顿时间较长,比较耗时)

注意:标记用的是三色标记法

更专业一点:

复制代码
标记 - 清除算法是通过 GC Roots 扫描标记存活对象,回收未标记对象的垃圾回收算法。
其核心流程简洁,但存在明显缺陷:标记阶段全堆遍历,对象数量多时常导致 GC 停顿久;回收后产生的内存碎片化,会引发大对象分配失败、后续内存分配和垃圾回收效率降低等问题。
该算法常应用于对停顿时间要求不是极端严格,且能通过其他机制一定程度缓解碎片化影响的场景(如老年代部分垃圾回收场景),同时也因这些特点,在与复制算法、标记 - 整理算法的对比中,有独特的适用范围和权衡考量。
  • 流程:

    1. 标记:遍历对象图,标记所有存活对象。
    2. 清除:遍历堆内存,回收未标记的对象(直接释放内存)。
  • 优缺点:

    • 优点:实现简单,无需移动对象。

    • 缺点:产生内存碎片 (零散的空闲内存无法分配大对象(数组));标记和清除过程耗时(全堆遍历)。

2. 复制算法(Copying)

自己的理解:

标记-复制算法:将内存分为两个大小相同的区域,每次只使用其中一个,当垃圾回收时将存活的对象复制到另一块区域,然后清除正在使用的区域。

优点是无内存碎片。

缺点是:首先当一个区域存活的对象太多时,需要较多的内存间复制,效率低。

第二个是浪费内存,每次只使用一半的内存。特别适合新生代,因为新生代每次存活的对象少,复制就少,性能影响就不那莫明显。

补充:

java 复制代码
HotSpot 里新生代用 8:1:1 的 Eden+Survivor 结构,本质也是这种算法的优化,既保留无碎片优势,又提高了内存利用率
  • 流程 :
    将内存分为两块等大区域 (如新生代的 Eden + s0、s1),每次只用其中一块。回收时,将存活对象复制到另一块空白区域,然后清空当前区域。

  • 优缺点:

    • 优点:无内存碎片,适合存活率低的区域(如新生代)。
    • 缺点:浪费内存 (使现有得可用空间变为原来得一半);复制对象有性能开销(小对象影响小,大对象成本高)。

    3. 标记 - 整理算法(Mark-Compact)

自己的理解:

标记-整理算法:标记过程和标记清除过程一样,首先是从GC Roots出发标记存活的对象,但后续过程它是将存活的对象移到内存一端,然后直接清除边界以外的内存。

优点是解决了内存碎片的问题,缺点是需要移动对象,可能有性能开销。

更全面一点:

复制代码
"标记 - 整理算法的标记阶段和标记 - 清除一致,都是从 GC Roots 出发标记存活对象。但后续它会把存活对象移动到内存的一端,然后清除边界外的所有内存。
优点是彻底解决了内存碎片化问题,避免大对象分配失败;缺点是移动对象时需要修改引用地址,可能带来性能开销,尤其是存活对象多的时候。
这种算法很适合老年代,因为老年代对象存活率高,用复制算法成本太高,用标记 - 清除会有碎片,而标记 - 整理能平衡这两点,虽然有移动成本,但老年代回收频率低,整体更合理。"
相关推荐
captain37621 分钟前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
心中有你021442 分钟前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
步行cgn1 小时前
Spring MVC + Thymeleaf 模板解析失败:从 500 错误到页面正常显示
java·spring·mvc
lgcgkCQ2 小时前
【AI 转型实战 1】SpringAI 入门:搭建基础大模型对话能力
java·ai·agent·rag·spring ai·mcp·langchain4j
Wang's Blog2 小时前
Java 项目实战:交友项目 - 用户体系集成总结
java·开发语言·交友
学到老活到老2 小时前
第 24 集:配置文件写了 80,Spring Boot 为什么读到 90?
java·后端·spring
tongyiixiaohuang2 小时前
供应商主数据同步实战:从易快报到金蝶云星空的单一策略落地
java·网络·数据库
鱼宵3 小时前
取集合第一个元素,Java 为什么要写三种写法?
java·windows·python·java21
学长毕设3 小时前
基于SpringBoot的餐厅管理系统-附源码
java·spring boot·后端
刚入门的大一新生4 小时前
Linux-线程互斥
java·开发语言