编程语言导论/垃圾回收
垃圾回收 (GC) 是一种自动内存管理的形式。垃圾回收器,或简称收集器,试图回收垃圾,即程序不再使用的对象所占用的内存。垃圾回收通常被认为是手动内存管理的相反,手动内存管理需要程序员指定要释放并返回到内存系统的对象。垃圾回收与其他内存管理技术一样,可能会占用程序总处理时间的很大一部分,因此会对性能产生重大影响。
在本节中,我们将描述三种形式的垃圾回收。
标记-清除收集器试图找到活动堆链接,并标记那些可达的块。然后它遍历堆,并将未标记的空闲块返回到空闲池。
标记-清除方法是第一个已知的垃圾回收策略。在此方法中,垃圾回收器从称为根集的点(程序中易于识别的对象集)开始扫描程序,并尝试从该点到达其他对象。收集器重复此扫描,直到它无法找到任何更多可达对象。每当找到一个对象时,就会设置其“正在使用”位。收集器完成标记对象后,它遍历整个堆,释放那些没有设置“正在使用”位的对象。
此方法有几个缺点,最显着的是在收集过程中必须暂停整个系统。这会导致程序定期(并且通常不可预测地)“冻结”,使实时和时间关键型应用程序无法实现。
在复制收集收集器中,内存被分成两部分;一次只使用其中一部分。当使用的一半已满时,将使用的块复制到另一个位置,并擦除旧的位置。
此方法有两个主要缺点。首先,它必须停止程序的执行才能将对象从堆的一部分移动到另一部分。其次,它必须更改程序对象指向的地址。这涉及更改程序中变量的值。在像 C 这样的语言中,你将对象的地址存储在一个整数中,这使得垃圾回收器更难确定哪些程序变量存储了对象的地址。
复制收集的最大优势在于,如果程序使用的内存大小小于正在使用的堆一半的大小,则无需复制,从而避免停止程序和更改对象的地址。
在引用计数收集器中,每个块都有一个指向它的堆链接计数器。当复制堆链接时,此计数器会增加,当丢弃链接时,它会减少。当计数器变为零时,该块将被释放。与跟踪垃圾回收相比,引用计数保证对象在变得不可达时立即被销毁。
引用计数的最大优势在于程序不需要停止来执行垃圾回收。最大的缺点是
- 使用额外的空间来存储引用计数器。
- 如果两个或多个对象相互引用,它们可以创建一个循环,其中任何一个对象都不会被回收,因为它们的相互引用永远不会让它们的引用计数变为零。