Java垃圾收集器如何处理自引用?

希望是一个简单的问题。 以循环链接列表为例:

class ListContainer { private listContainer next;  public void setNext(listContainer next) { this.next = next; } } class List { private listContainer entry;  } 

现在因为它是一个循环链接列表,当添加一个元素时,它在它的下一个变量中引用了它自己。 删除列表中的唯一元素时,条目设置为null。 是否需要将ListContainer.next设置为null以及垃圾收集器释放它的内存还是自动处理这样的自引用?

仅依赖于引用计数的垃圾收集器通常易于收集诸如此类的自引用结构。 这些GC依赖于对对象的引用数量的计数,以便计算给定对象是否可达。

非引用计数方法应用更全面的可达性测试来确定对象是否有资格被收集。 这些系统定义了一个始终被认为是可达的对象(或一组对象)。 任何可从此对象图中获得引用的对象都被视为不适合收集。 不能直接从此对象访问的任何对象。 因此,周期不会影响可达性,并且可以收集。

另请参阅跟踪垃圾收集器的Wikipedia页面。

如果您依赖于对引用进行计数以确定对象是否已死,则循环引用是一个(可解决的)问题。 没有java实现使用引用计数,AFAIK。 较新的Sun JRE使用多种类型的GC混合,我认为所有标记和扫描或复制。

您可以在Wikipedia上阅读有关垃圾收集的更多信息,以及有关Java GC的一些文章,例如此处和此处 。

对此的实际答案取决于实现。 Sun JVM跟踪一些根对象(线程等),当它需要进行垃圾收集时,跟踪哪些对象可以从那些对象中访问并保存它们,丢弃其余对象。 它实际上比允许一些优化更复杂,但这是基本原则。 此版本不关心循环引用:只要没有活动对象持有对死亡对象的引用,它就可以被GCed。

其他JVM可以使用称为引用计数的方法。 当为对象创建引用时,某些计数器会递增,当引用超出范围时,计数器会递减。 如果计数器达到零,则完成对象并收集垃圾。 但是,这个版本确实允许循环引用永远不会被垃圾收集。 作为一种安全措施,许多此类JVM都包含一种备份方法,用于确定哪些对象实际上已死亡,并定期运行以解析自引用并对堆进行碎片整理。

作为一个不回答的问题(现有答案已经足够),如果您对GC感兴趣,可能需要查看JVM垃圾收集系统上的白皮书。 (任何,只是谷歌JVM垃圾收集)

我对使用的一些技术感到惊讶,在阅读“Eden”等一些概念时,我第一次真正意识到Java和JVM实际上可以在速度上击败C / C ++。 (每当C / C ++释放一个对象/内存块时,就会涉及代码……当Java释放一个对象时,它实际上根本不做任何事情;因为在良好的OO代码中,大多数对象几乎立即被创建和释放,这非常有效。)

现代GC往往非常高效,管理旧对象的方式与新对象大不相同,能够控制GC短而半,或者长而彻底,并且许多GC选项可以通过命令行开关进行管理,所以它实际上是知道所有术语实际引用的内容很有用。

注意:我刚才意识到这是误导性的。 C ++的STACK分配速度非常快 – 我的观点是关于分配当前例程完成后能够存在的对象(我认为应该是所有对象 – 如果你打算这样做你不应该考虑的事情在OO中思考,但在C ++速度可能会使这不切实际)。

如果您只是在堆栈上分配C ++类,那么它的分配将至少与Java一样快。

Java收集任何无法访问的对象。 如果其他任何内容都没有引用该条目,那么它将被收集,即使它具有对自身的引用。

是Java垃圾收集器处理自我引用!

 How? 

有一些称为垃圾收集根(GC根)的特殊对象。 它们总是可以访问的,任何具有它们的对象都是可以访问的。

一个简单的Java应用程序具有以下GC根源:

  1. 主方法中的局部变量
  2. 主线程
  3. 主类的静态变量

在此处输入图像描述

为了确定哪些对象不再使用,JVM间歇性地运行非常适合称为标记和扫描算法的对象 。 它的工作原理如下

  1. 该算法遍历所有对象引用,从GC根开始,并将每个找到的对象标记为活动。
  2. 将回收未被标记对象占用的所有堆内存。 它只是标记为免费,基本上没有未使用的对象。

因此,如果无法从GC根目录访问任何对象(即使它是自引用或循环引用),它将进行垃圾收集。

简单地说,是的。 🙂

查看http://www.ibm.com/developerworks/java/library/j-jtp10283/

所有JDK(来自Sun)都有一个“达到能力”的概念。 如果GC无法“到达”某个物体,它就会消失。

这不是任何“新”信息(您的第一个受访者很好),但链接很有用,简洁是甜蜜的。 🙂