跳转至内容

编程语言导论/垃圾回收

来自维基教科书,开放的书籍,开放的世界

垃圾回收

[编辑 | 编辑源代码]

垃圾回收 (GC) 是一种自动内存管理的形式。垃圾回收器,或简称收集器,试图回收垃圾,即程序不再使用的对象所占用的内存。垃圾回收通常被认为是手动内存管理的相反,手动内存管理需要程序员指定要释放并返回到内存系统的对象。垃圾回收与其他内存管理技术一样,可能会占用程序总处理时间的很大一部分,因此会对性能产生重大影响。

在本节中,我们将描述三种形式的垃圾回收。


标记-清除

[编辑 | 编辑源代码]
朴素的标记-清除方法在包含八个对象的堆上运行。箭头代表对象引用。圆圈代表对象本身。对象 #1、#2、#3、#4 和 #6 从根集被强引用。另一方面,对象 #5、#7 和 #8 既没有从根集直接引用也没有间接引用;因此,它们是垃圾。

标记-清除收集器试图找到活动堆链接,并标记那些可达的块。然后它遍历堆,并将未标记的空闲块返回到空闲池。

标记-清除方法是第一个已知的垃圾回收策略。在此方法中,垃圾回收器从称为根集的点(程序中易于识别的对象集)开始扫描程序,并尝试从该点到达其他对象。收集器重复此扫描,直到它无法找到任何更多可达对象。每当找到一个对象时,就会设置其“正在使用”位。收集器完成标记对象后,它遍历整个堆,释放那些没有设置“正在使用”位的对象。

此方法有几个缺点,最显着的是在收集过程中必须暂停整个系统。这会导致程序定期(并且通常不可预测地)“冻结”,使实时和时间关键型应用程序无法实现。

复制收集

[编辑 | 编辑源代码]

复制收集收集器中,内存被分成两部分;一次只使用其中一部分。当使用的一半已满时,将使用的块复制到另一个位置,并擦除旧的位置。

此方法有两个主要缺点。首先,它必须停止程序的执行才能将对象从堆的一部分移动到另一部分。其次,它必须更改程序对象指向的地址。这涉及更改程序中变量的值。在像 C 这样的语言中,你将对象的地址存储在一个整数中,这使得垃圾回收器更难确定哪些程序变量存储了对象的地址。

复制收集的最大优势在于,如果程序使用的内存大小小于正在使用的堆一半的大小,则无需复制,从而避免停止程序和更改对象的地址。

引用计数

[编辑 | 编辑源代码]

引用计数收集器中,每个块都有一个指向它的堆链接计数器。当复制堆链接时,此计数器会增加,当丢弃链接时,它会减少。当计数器变为零时,该块将被释放。与跟踪垃圾回收相比,引用计数保证对象在变得不可达时立即被销毁。

引用计数的最大优势在于程序不需要停止来执行垃圾回收。最大的缺点是

  • 使用额外的空间来存储引用计数器。
  • 如果两个或多个对象相互引用,它们可以创建一个循环,其中任何一个对象都不会被回收,因为它们的相互引用永远不会让它们的引用计数变为零。
华夏公益教科书