java垃圾回收机制

Posted by WK on 2025-04-10
Estimated Reading Time 4 Minutes
Words 1.3k In Total
Viewed Times

垃圾回收机制

Java 的垃圾回收机制(Garbage Collection, GC)是 Java 虚拟机(JVM)的核心功能之一,旨在自动管理内存,减少开发人员手动管理内存的工作,同时避免内存泄漏和内存溢出等问题。

一、垃圾回收的目标

  • 回收无用对象:释放被废弃对象占用的堆内存。
  • 提高内存利用率:通过整理内存碎片,使内存分配更加高效。
  • 简化开发:开发者无需手动管理内存,专注于业务逻辑。

二、垃圾回收的基本流程

垃圾回收的主要任务是识别并回收不再使用的对象。其基本流程包括以下几个步骤:

  1. 判断对象是否存活
    为了确定哪些对象可以被回收,JVM 使用以下两种算法来判断对象是否仍然存活:

    • 引用计数法(Reference Counting)
      • 每个对象维护一个引用计数器,每当有一个地方引用它时,计数器加 1;当引用失效时,计数器减 1。
      • 缺点:无法处理循环引用(两个对象互相引用,但它们都无法被外部访问)。
      • JVM 并未采用引用计数法。
    • 可达性分析(Reachability Analysis)
      • JVM 通过 GC Roots 作为起点,从这些根节点出发,沿着引用链向下搜索,所有能够被访问到的对象都被认为是存活的。
      • GC Roots 通常包括:
        • 虚拟机栈中引用的对象(局部变量表中的引用)。
        • 方法区中类静态属性引用的对象。
        • 方法区中常量引用的对象。
        • 本地方法栈中 JNI(Native 方法)引用的对象。
  2. 标记与清除
    在确定了哪些对象是存活的之后,垃圾回收器会执行以下操作:

    • 标记阶段:遍历堆内存,标记所有存活的对象。
    • 清除阶段:回收未被标记的对象所占用的空间。
  3. 垃圾回收的算法
    JVM 提供了多种垃圾回收算法,不同的算法适用于不同的场景:

    • 标记-清除算法(Mark-Sweep)
      • 过程:
        • 首先标记所有需要回收的对象。
        • 然后直接清除这些对象。
      • 优点:实现简单。
      • 缺点:
        • 效率较低,标记和清除过程都需要遍历整个堆。
        • 容易产生内存碎片,导致后续大对象分配失败。
    • 复制算法(Copying)
      • 过程:
        • 将堆内存划分为两个相等的区域(From 空间和 To 空间)。
        • 每次只使用其中一个区域,当这个区域满了时,将存活的对象复制到另一个区域,并清空原区域。
      • 优点:
        • 解决了内存碎片问题。
        • 回收效率高,适合对象存活率低的场景。
      • 缺点:浪费一半的内存空间。
    • 标记-整理算法(Mark-Compact)
      • 过程:
        • 标记阶段与标记-清除算法相同。
        • 清除阶段不同:将所有存活的对象向一端移动,然后清理掉边界之外的内存。
      • 优点:
        • 解决了内存碎片问题。
        • 不需要额外的空间。
      • 缺点:整理阶段需要移动对象,效率低于复制算法。
    • 分代收集算法(Generational Collection)
      这是现代 JVM 中最常用的垃圾回收算法,基于“对象的生命周期”进行优化:
      • 新生代(Young Generation)
        • 大部分对象都在这里分配。
        • 使用复制算法,因为大部分对象很快就会成为垃圾(朝生夕死)。
        • 新生代进一步分为三个部分:
          • Eden 区:新创建的对象首先分配在这里。
          • Survivor 区(S0 和 S1):每次 Minor GC 后,存活的对象会被移动到 Survivor 区。
        • 当 Survivor 区不足以容纳存活对象时,对象会被晋升到老年代。
      • 老年代(Old Generation)
        • 存放生命周期较长的对象。
        • 使用标记-清除或标记-整理算法,因为对象存活率较高。
      • 永久代/元空间(Permanent Generation/Metaspace)
        • 存储类信息、常量池、静态变量等。
        • 在 JDK 8 之前称为永久代,JDK 8 及以后改名为元空间,并存储在本地内存中。

三、垃圾回收器

JVM 提供了多种垃圾回收器,每种回收器都有其特点和适用场景:

  1. Serial 收集器

    • 特点:单线程串行工作、适合单核 CPU 环境。
    • 应用场景:客户端模式下的小型应用。
  2. Parallel 收集器(吞吐量优先)

    • 特点:
      • 多线程并行工作,充分利用多核 CPU。
      • 关注吞吐量(Throughput),即运行用户代码的时间占总时间的比例。
    • 应用场景:后台计算服务。
  3. CMS 收集器(响应时间优先)

    • 特点:以最短的停顿时间为目标。基于标记-清除算法。
    • 优点:适合对响应时间要求较高的应用(如 Web 服务器)。
    • 缺点:容易产生内存碎片,且对 CPU 资源敏感。
  4. G1 收集器

    • 特点:
      • 将堆划分为多个大小相等的 Region,按需回收。
      • 同时兼顾吞吐量和停顿时间。
    • 优点:适合大规模应用,尤其在大堆内存场景下表现优异。
    • 应用场景:企业级应用。

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !