GC 算法

垃圾判定算法

  1. 引用计数法

    记录每个对象的使用次数,某个对象每增加一次引用,其引用计数器+1,当引用失效,引用计数器-1,当引用计数器为0,对象就视为垃圾

    • 优点:实现起来很简单

    • 缺点:无法解决循环引用的问题,如下图(明明是垃圾,但是没有被回收,这就是内存泄露

    java 没有采用引用计数,但是因为其原理简单还是有很多使用的场景,比如 python,怎么解决呢?

    手动解除(自己再做一个算法,发现循环引用的内存泄露就手动接触关联);或者使用弱引用类型(强弱软需)

  2. 可达性分析算法

    以 GC Roots 为起点,找整个引用链,如果对象没有在任何一个引用链就视为垃圾

    1. 优点:解决了循环引用的问题,原理还是比较简单的
    2. 缺点:某个时刻进行 GC,首先要确定 GC Root 对象,虚拟机栈是 GC Root 的一部分,为了准确性需要暂停素有线程,这就是 STW 的原因
    3. 常见的 GC Root 对象:虚拟机栈里引用的对象、类静态变量引用的对象、synchronized 的锁对象等

    可达性分析算法解决了循环引用的内存泄露,但是不是说可达性分析算法就不会发生内存泄露了

    比如各种连接,数据库连接,网络连接,IO连接等,用完要显示标明关闭连接,不然每次 GC 就会发现还存在引用链,不会回收

垃圾回收算法

  1. 标记-清除算法

    根据可达性分析算法把非垃圾对象进行标记,没标记的就是垃圾,清除没有标记的,留下的对象还是在原来的位置上

    这是最基础的算法,别的算法都是基于此不断改进,不足的地方

    • 效率不高(要看跟谁比,比如标记-复制就要快些):先递归确定引用链,找到有用的对象,然后整堆遍历清除垃圾对象
    • 存在内存碎片:会产生大量不连续的内存碎片,导致可能无法给大对象分配内存
  2. 复制算法

    也要先根据可达性分析算法遍历找到有用的对象,但是不标记了,直接复制到另一个区域,然后把原来的区域全部清空

    • 优点:相较于 标记-清除效率更高,因为没有标记和清除的过程,也没有内存碎片了
    • 缺点:需要两倍空间(虽然没有碎片了,但是要两倍空间);如果存活对象本来就很多,就有点得不偿失了
  3. 标记-压缩 或 标记-整理算法

    比标记-清除多了异步整理的操作

    • 优点:解决了标记-清除、复制的问题(碎片和两倍空间)
    • 缺点:效率不高。比标记-清除多了整理的步骤;比复制多扫描了空间(因为复制算法要保证一半的区域是空的)
  4. 分代收集算法

    1. 这不是一种算法,只是也有不少人在这样说,具体是根据 jvm 不同的区域使用合适的算法,算法还是这三种:标记-清除、复制、标记-压缩
    2. 因为新生代 GC 很频繁,并且很多对象在新生代创建并死亡,所以新生代适合 标记-清除 算法(这就是为什么新生代幸存区是两个)
    3. 老年代空间比较大、对象存活时间也比较长,可能回收的内存并不是很多,所以适合 标记-压缩 算法
posted @   CyrusHuang  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示