小工具知识网

当前位置: 首页 > 行业知识 > JVM(垃圾回收机制 ---- GC)

行业知识

JVM(垃圾回收机制 ---- GC)

2026-11-15 13:20:14 来源:互联网转载

啥是垃圾?

不再使���的内存


啥是垃圾回收机制?

自动释放不用的内存

注意: GC 主要是针对 堆 进行的

GC的基本操作单位是 对象, 即GC’回收的是整个对象都不使用的情况


GC 的优缺点

好处: 省心, 写代码简单, 不易出错

缺点: 需要消耗额外资源, 有额外性能开销 , 此外, 易触发 STW 问题

STW 问题

Stop The World

如果内存中垃圾很多, 此时触发一次 GC 操作, 开销可能非常大, 还可能会触发一些锁操作, 因此会导致业务代码无法正常执行


GC 实际工作过程

  1. 找到垃圾 / 判定垃圾
  2. 进行垃圾 (对象) 的释放

找到垃圾 / 判定垃圾

关键是看这个有没有引用 “指向” 它, 没有引用指向的对象, 自然不可能被用到, 就是垃圾了

两种典型实现:

  1. 引用计数 (py / php 做法)

    给每个对象分配一个计数器, 每次创建一个引用指向该对象, 计数器加一, 每次删除一个该对象的引用, 计数器减一, 当计数器为0, 该对象自然就是垃圾了

问题 :

  • 内存空间利用率低 (计数器本身需要存储)
  • 存在循环引用的问题 (py / php 使用引用计数, 需要搭配其他机制来避免循环引用)
    1. 可达性分析 (Java 做法)

      将整个 Java 中所有的对象, 通过 链式 / 树形 结构, 整体给串起来

      可达性分析,就是把所有的对象被组织起来的结构视为树, 从树的根节点出发, 遍历树, 所有能被访问到的对象, 标记成 “可达”

      JVM 再比对自己手里的对象名单, 将不可达的对象进行回收(每次 new 一个对象的时候, JVM 都会有记录)

    • 可达性分析类似树遍历, 相对于引用计数会慢一些 (因此不必一直执行, 每隔一段时间执行一次就ok ---- “虽迟但到” )
    • 可达性分析遍历的起点 ---- GCroots (一个代码中会有很多起点, 每个起点往下扫一遍, 就完成一次分析)

      清理垃圾 (此处为几种垃圾回收算法)

      1. 标记清理

        简单粗暴的做法, 如果灰色区域为垃圾, 白色不是, 则直接清除

        问题:

      • 会产生零散的内存碎片

        2.复制算法

        把内存空间均分成两份, 每次将不是垃圾的对象复制到另外一边, 然后把整个含垃圾的区域清理掉

        问题 :

        • 空间利用率低 (每次只能用到一半空间)
        • 如果垃圾少, 有效对象多, 复制成本就会很大
          1. 整理标记

            类似顺序表删除中间元素, 将不是垃圾的对象从前往后依次排开, 清理剩余空间

          • 保证了空间利用率, 也解决了内存碎片问题
          • 显而易见, 本做法效率也不高

            分代回收

            基于上述基本策略, 搞了一个符合策略 “分代回收”

            历史基本规律: 如果一个东西存在的时间比较长, 那么大概率还会继续长时间存在下去

            该规律对于 Java 同样有效, Java 对象要么生命周期特别长, 要么特别短

            引入概念: 年龄 ---- 熬过 GC 的轮次 (没被清理)

            将堆分成一系列区域

            Minor GC : 新生代 GC

            Full GC : 老年代 GC

            • 刚创建的对象, 年龄为 0 ,放到伊甸区
            • 熬过一轮 GC ,放入幸存区 (复制算法)
            • 幸存区中对象, 周期性接收 GC 考验, 如果变成垃圾, 就被释放, 如果不是垃圾, 就拷贝到另外一个幸存区 (俩幸存区同一时刻只使用一个), 在二者间来回拷贝 (复制算法)
            • 在幸存区中经过了多轮考验后, 进入老年代
            • 老年代也要周期性 GC 扫描, 只是频率更低
            • 如果老年代的对象是垃圾了, 使用标记整理的方式进行释放

上一篇:unity webgl 系列(2):从webgl内存中下载文件到本地硬盘

下一篇:手游爱好者必选!独家推广平台引领潮流之巅