Java - 自动垃圾回收如何处理 LinkedList?

3
在C++中,您需要手动删除LinkedList中的节点:
  Node* node1 = new Node(s);
  Node* node2 = new Node(s);
  Node* node3 = new Node(s);

  node1 -> next = node2;
  node2 -> next = node3;

  //remove node2 by: 
  delete node2;
  node1 -> next = node3;

对于Java(这是我学习Java的前两天),自动垃圾回收如何知道何时采取行动?会:

    node1.next = node3;

be adequate?

3个回答

3

一旦Java中的对象不再有引用与其相关,则该对象将成为垃圾回收的候选对象。

因此,如果您拥有一个如下所示的单向链表

(1) -> (2) -> (3)

假设 head = node 1,那么设置 head.next = head.next.next 将允许在某个时刻回收 node2。然而,在您的示例中,只有在您显式声明 node2 = null 并且加上 node1.next = node3 才能使 node2 消失,因为引用作为 node2 会保留它的范围。请注意,node2 = null 实际上不会对 node2 曾经指向的 Node 对象做任何事情。相反,它只是将该引用(因为 Java 中的所有对象都是指针)设置为 null。

1
“在范围内”并不完全正确。作用域是一种词法结构,与对象的生命周期只有松散的关系。当对象不再被任何正在运行的代码引用时,它们将变得可以进行垃圾回收,这与“在范围内”不同。 - Daniel Pryden
这是一个公正的区分。我想更恰当的说法是,大多数情况下,垃圾回收器能够捡起对象,因为它们的引用超出了范围,从而使它们变得不可访问。感谢你提供更好的技术解释! - CollinD
2
实际上,您编辑后的答案也不完全正确,因为对象 可以 在其引用仍在作用域内时变得不可访问。基本上,一旦编译器可以证明引用不再被读取,它就可以自由地重用该帧中的本地变量来存储其他内容,此时所涉及的对象不再具有任何引用并且符合进行垃圾回收的条件。Raymond Chen在他的博客文章何时使对象符合垃圾回收条件?中解释了这一点(针对C#,虽然Java类似)。 - Daniel Pryden
1
@Daniel Pryden:你说得对,Java的类似问题在这里讨论:这里这里 - Holger

2

Java垃圾回收器定期遍历整个对象引用映射,以查找并删除未被引用或循环引用的对象。您可以提示JVM启动垃圾回收的迭代,但您无法实际指示JVM进行确定性垃圾回收。

在您的情况下

node1.next = node3;

如果node2不再具有任何对象引用,那么这将是足够的。


1
假设您以某种方式修改了LinkedList,使得不再有对node2的引用,垃圾收集器可以释放其内存。换句话说,只要没有其他对node2的引用,node1.next = node3;就足够了。请注意保留HTML标签。

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