Queue dequeue()中的Java垃圾收集示例代码
我在一门关于算法的课程中学习了队列实现的代码,并观察了作者使用的dequeue()代码:Queue dequeue()中的Java垃圾收集示例代码,java,garbage-collection,Java,Garbage Collection,我在一门关于算法的课程中学习了队列实现的代码,并观察了作者使用的dequeue()代码: private Node first, last; private class Node { String item; Node next; } public boolean isEmpty() { return first == null; } // Code segment in doubt public String dequeue() { String item
private Node first, last;
private class Node {
String item;
Node next;
}
public boolean isEmpty() {
return first == null;
}
// Code segment in doubt
public String dequeue() {
String item = first.item;
first = first.next;
if (isEmpty()) last = null;
return item;
}
这里,first和last分别指向队列中的第一个和最后一个元素,这是可以理解的。我对作者使用的dequeue()中的代码有点怀疑。因为,他只是在做:
first = first.next;
未将first.next赋值为null。它会不会留下一个悬空引用(或游荡),这将阻碍JVM的垃圾收集机制?我有点困惑,dequeue()的代码应该是这样的吗?(我确信在C/C++中,代码应该如下所示,但我想知道在这种情况下JAVA的预期行为)
如果有人能给我指出一个详细介绍这个主题的资源,并提供一些很好的例子,我也将不胜感激。设置
old.next=null
是不必要的,因为old
已准备好进行垃圾收集(first=first.next
分配消除了它最后一次的实时引用(一旦退出队列,垃圾收集器就不会跟踪它的任何引用。假设队列中有两个对象:A和B
first
指向A
和first。next
指向B
(换句话说A.next==B
)
对A
的唯一引用是Queue#first
变量
first = first.next; // first == B
没有人再引用
对象,因此它有资格进行垃圾收集。如果您的队列未实现为双队列
(意味着您可以同时访问队列中的.Next和.Prev),然后将first
设置为first。next
,将不会有指向first
的引用或指针,然后垃圾收集线程将知道它(first
)需要进行垃圾收集(相关内存将被释放).只有来自活动对象的引用才重要。这些引用确定哪些对象是活动的
如果一个对象有一个对活动对象的引用,但它没有被引用,则将收集该引用。(JVM不使用引用计数,并且不需要更新此计数)
另一种情况是,如果两个对象再次相互引用(但其他任何对象都不引用),那么这很好,因为只有可以从根节点(例如线程)访问的对象被保留,其他所有对象都被收集。新的“第一个”后面的“old.next”的引用如何当“old.next”仍然引用“first”时,GC如何知道它必须对“old”进行垃圾收集?@sultan.of.swing垃圾收集器将忽略old.next
引用,因为old
不是活动的。收集器跟踪活动对象,因此如果old
是活动的,那么它也将跟踪old.next
引用;但是,old
不是活动的(一旦退出队列
退出),因此,它保留的引用并不重要。.@sultan.of.swing将堆中的所有对象都绘制成一棵树(实际上它们形成了一个图形,但树更容易可视化)。树的一个节点(“父”节点)指向两个“子”节点。删除“父”节点不必将父节点的“子节点”引用设置为null,因为当垃圾收集器遍历树时,它不会遍历“父节点”,因为您已将其从树中删除(因此它不可访问且不活动)我喜欢你把队列中的对象比喻成树,但是实际行为是什么,GC如何优化和知道所有的活引用?它是如何保持所有变量和当前引用的状态的?@ SultA.Of.Switter是一个好的开始的地方。最好的深度资源是C++。structor,但在Java中,old和first是对同一对象的引用。因此,您应该将this.first设置为null,这将使结构混乱,以便将来调用。但在原始实现中,first指向的原始对象不再具有对它的任何引用(假设队列只能向前遍历)。这使原始的第一个节点有资格进行垃圾收集。[旁白],不应dequeue()
first callisEmpty()
,否则,字符串item=first.item
调用?@Kevin我想你是对的,必须测试一下空引用异常。我从幻灯片中逐字复制了代码。
first = first.next; // first == B