README.md 4.8 KB

垃圾回收算法

序章

GC 是 Garbage Collection 的简称, 中文翻译 垃圾回收

GC 把 程序不用打内存空间 视为垃圾

GC 要做的两件事情

  1. 找到内存空间里的垃圾
  2. 回收垃圾, 让程序员能再次利用这部分空间

就 C++ 语言来说申请内存尚不存在什么问题, 但是释放不要的内存空间时就必须一个不漏的释放, 这是非常麻烦的一件事情。如果忘记释放内存, 改内存空间就会发生内存泄漏,即无法使用。如果放任内存泄漏不处理,总有一刻内存会被占满,甚至还可能导致系统崩溃

另外,如果释放内存空间时忘记将指向该内存空间的指针设置为 NULL 或者 nullptr 就会导致指针指向已经被释放的内存空间,处于一种悬挂的状态,称之为 悬垂指针。如果程序中错误的引用类悬垂指针,就会产生无法预期的 Bug

另外,也有释放错内存空间的可能

综上几种情况,可见 GC 的重要性

1960年 Jon McCarthy 发布了 清除算法

1960年 George E. Collins 发布了 引用计数 的 GC 算法

1963年 Marvin L. Minsky 发布了 复制算法

现在常用的 GC 算法大多是从上述三种算法中衍生出来的产物

GC 更像是一个无名英雄, 默默做着贡献。 但是 GC 基本上是高负载处理, 需要花费一定的时间。当编写动作游戏这样追求即时性的程序时,就必须尽量压低 GC 导致的最大暂停时间。

基本概念

头 和 域

在 GC 世界中对象表示的是 通过应用程序利益哦那个的数据的集合

对象配置在内存空间里。GC 根据情况将配置好的对象进行移动销毁操作

一般来说,对象由构成

我们将对象中保存对象本身信息的部分称为 头,一般包括 对象的大小对象的种类 信息

知道对象的大小和种类,就能够判断内存中存储的对象的边界

此外,头 中事先存有运行 GC 所需的信息,根据算法的不同存储的信息也不同

比如标记-清除算法中,头 里面就存了一个 falg 用来记录对象是否被标记

我们把对象使用者在对象中可访问的部分称为 。可以将其想成C语言中结构体的成员。对象使用者会引用或替换对象的域值,对象使用者基本上无法直接更改的信息

域中的数据类型大致分为两种: 指针,非指针

指针是只想内存空间中某块区域的值;非指针指的就是编程中直接使用值本身

指针

通过 GC 对象会被销毁或保留。 GC 会根据对象的指针去搜寻其他对象; 另外 GC 对非指针不进行任何操作

首先,需要注意语言处理程序是可以辨别指针和非指针

另一点,指针是要只想对象的哪部分,如果指针指向对象首地址以外的部分,那么GC就会变得非常复杂。所以大多数语言中,指针都默认指向对象的首地址

这里把上图中的 B 和 C 对象称为 A 的字对象, 对某个对象的子对象进行某项处理是 GC 的基本操作

mutator

mutator 意为 改变某物 的意思。说到要改变什么,在 GC 中自然是 GC 对象间的引用关系

mutator是垃圾回收机制中的程序执行部分,负责分配、使用和维护对象之间的引用关系。垃圾回收器需要与mutator并行工作,以确保内存的有效管理和回收

  • 内存分配:当程序需要分配新的内存来存储对象时,mutator负责请求内存分配。它会向垃圾回收器申请一块可用的内存空间,并将对象存储在其中

  • 内存使用:mutator负责访问和修改分配给它的内存空间中的对象。它可以读取和更新对象的字段、执行方法和算法等

  • 对象引用:mutator会维护对象之间的引用关系。当一个对象引用另一个对象时,mutator会将引用信息写入内存中的字段或变量。这些引用关系构成了对象图,垃圾回收器根据对象图进行垃圾回收操作

堆 指的是用于动态存放对象的内存空间,当 mutator 申请存放对象时,所需的内存空间就会从这个堆中被分配给 mutator

GC 是管理堆中已分配对象的机制。在开始执行 mutator 前, GC 要分配用于堆的内存空间。一但开始执行 mutator,程序就会按照 mutator 的要求在堆中存放对象

活动对象/非活动对象

将分配到内存空间中的对象中那些能够通过 mutator 引用的对象称为 活动对象;反之不能通过程序引用的对象称为 非活动对象

非活动对象就是我们说的 垃圾

GC 会保留活动对象,销毁非活动对象。当销毁非活动对象时,其原本占据的内存空间会得到解放,供下一个要分配的新对象使用