常见的GC算法(GC的背景与原理)

常见的GC算法(GC的背景与原理)

GC 是英文词汇Garbage Collection的缩写,中文一般直译为 “垃圾收集”。当然也会说 “垃圾回收”。

f37a9c99-3c14-4c8c-b285-0130a598c756.jpg

三种垃圾收集器实现(Paraller/CMS/G1)

手动内存管理

之前有C/C++编程经验、或者了解计算机原理的同学,会很容易理解 “内存分配” 和 “内存释放” 和两个概念。

计算机程序在执行过程中,需要有地方来存放输入参数、中间变量,以及运算结果,之前的文章有提到,我们知道这些会存放到栈内存中。

像C/C++的编程,需要使用完资源后,手动调用清除内存操作,这类归属于手动内存管理。

弊端就是:代码经手人多了,很可能不清楚哪些是需要清理的,造成管理混乱。

引用计数法

GC 垃圾收集器就像仓库部门,负责分配内存,负责追踪这些内存的使用情况,并在合适的时候进行释放。

8442223.png

但是,如果业务变得更复杂。仓库之间需要协同工作,有了依赖关系之后。

8648060.png

这时候单纯的引用计数就会出问题,循环依赖的仓库/对象没办法回收,就像数据库的死锁一样让人讨厌,你没法让它自己变成0。

这种情况在计算机中叫做 “内存泄漏”, 该释放的没释放,该回收的没回收。

如果依赖关系更复杂,计算机的内存资源很可能用满,或者说不够用,内存不够用则称为 “内尺寸溢出”。

这样我们知道了引用计数法的一些缺陷,有没有办法解决呢?办法总比困难多,我找个人专门来排查循环计数行了吧,一个不够就两个…但如果仓库成千上万,或者上亿呢?还是能解决的,最多不就是慢点嘛。

  • 第一代自动垃圾回收算法,使用的是引用计数。针对每个对象,只需要记住被引用的次数,当引用计数变为0时,这个对象就可以被安全地回收了,著名的示例是C++的共享指针;
  • 第二代自动垃圾回收算法,被称为 “引用追踪”,JVM 使用的各种垃圾回收算法都是基于引用追踪方式的算法。
标记清除算法(Mark and Sweep)

前面讲了引用计数里需要查找所有的对象计数和对象之间的引用关系。那么如何来查找锁有对象,怎么来做标记呢?

为了遍历所有对象,JVM明确定义了什么是对象的可达性。

有一类很明确具体的对象,称为垃圾回收根元素,包括:

  • 局部变量(Local variables)
  • 活动线程(Active threads)
  • 静态域(Static fields)
  • 其他对象

JVM 使用标记—清除算法,来跟踪所有的可达对象(包括存活对象),确保所有不可达对象占用的内尺寸都能被重用。其中包含两步:

  • Marking(标记):遍历所有的可达对象,并在本地内存中分门别类记下。
  • Sweeping(清除):这一步保证了,不可达对象所占用的内存,在之后进行内存分配时可以重用。

JVM中包含了多种GC算法,如Parallel Scavenge(并行清除)Parallel Mark + Coyp(并行标记+复制)CMS,他们在实现上略有不同,但理论上都采用了以上两个步骤。

标记清除算

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值