GC 算法
垃圾判定算法
-
引用计数法
记录每个对象的使用次数,某个对象每增加一次引用,其引用计数器+1,当引用失效,引用计数器-1,当引用计数器为0,对象就视为垃圾
-
优点:实现起来很简单
-
缺点:无法解决循环引用的问题,如下图(明明是垃圾,但是没有被回收,这就是内存泄露)
java 没有采用引用计数,但是因为其原理简单还是有很多使用的场景,比如 python,怎么解决呢?
手动解除(自己再做一个算法,发现循环引用的内存泄露就手动接触关联);或者使用弱引用类型(强弱软需)
-
-
可达性分析算法
以 GC Roots 为起点,找整个引用链,如果对象没有在任何一个引用链就视为垃圾
- 优点:解决了循环引用的问题,原理还是比较简单的
- 缺点:某个时刻进行 GC,首先要确定 GC Root 对象,虚拟机栈是 GC Root 的一部分,为了准确性需要暂停素有线程,这就是 STW 的原因
- 常见的 GC Root 对象:虚拟机栈里引用的对象、类静态变量引用的对象、synchronized 的锁对象等
可达性分析算法解决了循环引用的内存泄露,但是不是说可达性分析算法就不会发生内存泄露了
比如各种连接,数据库连接,网络连接,IO连接等,用完要显示标明关闭连接,不然每次 GC 就会发现还存在引用链,不会回收
垃圾回收算法
-
标记-清除算法
根据可达性分析算法把非垃圾对象进行标记,没标记的就是垃圾,清除没有标记的,留下的对象还是在原来的位置上
这是最基础的算法,别的算法都是基于此不断改进,不足的地方:- 效率不高(要看跟谁比,比如标记-复制就要快些):先递归确定引用链,找到有用的对象,然后整堆遍历清除垃圾对象
- 存在内存碎片:会产生大量不连续的内存碎片,导致可能无法给大对象分配内存
-
复制算法
也要先根据可达性分析算法遍历找到有用的对象,但是不标记了,直接复制到另一个区域,然后把原来的区域全部清空
- 优点:相较于 标记-清除效率更高,因为没有标记和清除的过程,也没有内存碎片了
- 缺点:需要两倍空间(虽然没有碎片了,但是要两倍空间);如果存活对象本来就很多,就有点得不偿失了
-
标记-压缩 或 标记-整理算法
比标记-清除多了异步整理的操作
- 优点:解决了标记-清除、复制的问题(碎片和两倍空间)
- 缺点:效率不高。比标记-清除多了整理的步骤;比复制多扫描了空间(因为复制算法要保证一半的区域是空的)
-
分代收集算法
- 这不是一种算法,只是也有不少人在这样说,具体是根据 jvm 不同的区域使用合适的算法,算法还是这三种:标记-清除、复制、标记-压缩
- 因为新生代 GC 很频繁,并且很多对象在新生代创建并死亡,所以新生代适合 标记-清除 算法(这就是为什么新生代幸存区是两个)
- 老年代空间比较大、对象存活时间也比较长,可能回收的内存并不是很多,所以适合 标记-压缩 算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具