垃圾回收 - 孤立的LinkedList链接

17
假设您有引用 A -> B -> C -> D。 当您从 A 中删除对 B 的引用时,您将得到一系列孤立的对象 B -> C -> D

即使没有办法访问它们(因为没有对 B 的引用),CD 是否会被垃圾收集器回收?

我想像垃圾收集器会聪明地解决任何此类依赖关系。

然而,我查看了 LinkedList 类的source code,发现与此信念相反的事情。 我注意到当列表被 clear() 时,每个链接的所有引用都被显式设置为 null,因此使其成为一个 O(n) 操作。 这样做的原因/好处是什么?

2个回答

13

看起来确实有点奇怪。也许显式拆卸列表的原因是为了清除现有迭代器、子列表以及父列表。

肯定不是为了加速垃圾回收。垃圾收集器不会遍历不可达对象中的引用,所以将其置空并不会产生任何影响。

更新

该方法的更近版本具有以下注释:

// Clearing all of the links between nodes is "unnecessary", but:
// - helps a generational GC if the discarded nodes inhabit
//   more than one generation
// - is sure to free memory even if there is a reachable Iterator

因此,在某些情况下,垃圾回收会有益处。 假设旧一代的Node包含对年轻一代对象(例如Node或元素)的引用,则在收集年轻一代时,该引用将成为“根”,导致保留年轻一代对象,即使旧一代Node不可访问。 除非旧一代被收集,否则该状态将继续存在。老一代垃圾回收发生得很少。

如果您遍历链表并拆卸它,则包含旧->新引用的变量将被分配一个null。 该分配的写屏障会导致(立即或在GC时间)原始引用不再是“根”。 因此,年轻一代中的对象现在可以被回收,并且不会“存活”到较旧的一代(这将提前需要收集该代的时间)。

可以想象,垃圾回收的好处超过了解开链表的成本...平均而言,或在成本灾难性的情况下。

有关更多信息,请参见Jones和Lins的“动态内存管理的垃圾回收算法”。 这在我的(第一版)副本的第7.5章中。


一般来说,最好放弃一个Collection对象并重新开始,而不是清除其以供重用。


1
啊是的,这完全正确!IteratorListIterator都包含对内部节点的引用。然而,SubList却没有。 - tskuzzy
@shmosel 什么可以使代际垃圾回收受益? - Kevin Krumwiede
@KevinKrumwiede 我们正在讨论...拆卸LinkedList - shmosel
@shmosel 请明确一下,您是在反驳还是支持“最好将整个列表丢弃”的说法?我查看了 GrepCode 上的 LinkedList 源代码,没有找到您所提到的内容。(我知道,这个帖子非常古老...) - Kevin Krumwiede
@KevinKrumwiede 没有关联。我的意思是说,当调用clear()时,断开每个节点会带来一些GC好处,而不仅仅是丢弃端点。您可以在此处查看更新后的源代码:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/LinkedList.java#LinkedList.clear%28%29. - shmosel
显示剩余2条评论

3
是的,假设只有B引用了它们,C和D将被垃圾回收。这是因为它们不可从应用程序对象图的根对象中访问。
我想标记LinkedList实现中每个链接为null的原因是为了防止内存泄漏。可能会有一些东西在LinkedList外部抓住头节点。如果发生这种情况,即使LinkedList已被清除,它也会保持所有其他节点的活动状态。

此外,将它们设为null可以使垃圾回收器更有效地清除它们,而无需遍历对象图,对吗? - OverZealous
当垃圾回收被触发时,整个对象图将被遍历,并将对象标记为“正在使用”。所以,是的,我想这会使遍历变得更短。 - nicholas.hauschild
实际上,只有可达对象图会被典型的垃圾收集器遍历。从B到C和从C到D的链接不会被遍历,因此将它们置空并不能提高性能。 - Stephen C
@Stephen C:抱歉,我表达得不够清楚。我在谈论可达对象图。我还假设将以前可达的值置空将使遍历变短。我想今天可能是我误解了每个人... - nicholas.hauschild
1
除非有外部引用头节点的方法,否则这是正确的,因为它是“私有的”,并且没有获取器。 - tskuzzy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接