希望是一个简单的问题.以循环链接列表为例:
class ListContainer { private listContainer next; <..> public void setNext(listContainer next) { this.next = next; } } class List { private listContainer entry; <..> }
现在因为它是一个循环链接的列表,当添加一个elemnt时,它在它的下一个变量中有一个对它自己的引用.删除列表中唯一的元素时,条目设置为null.是否需要将ListContainer.next设置为null以及垃圾收集器释放它的内存还是自动处理这样的自引用?
仅依赖于引用计数的垃圾收集器通常易于收集诸如此类的自引用结构.这些GC依赖于对对象的引用数量的计数,以便计算给定对象是否可达.
非引用计数方法应用更全面的可达性测试来确定对象是否有资格被收集.这些系统定义了一个总是被认为是可达的对象(或一组对象).任何可从此对象图中获得引用的对象都被视为不适合收集.不能直接从此对象访问的任何对象.因此,循环不会最终影响可达性,并且可以收集.
另请参阅跟踪垃圾收集器的Wikipedia页面.
如果您依赖于对引用进行计数以确定对象是否已死,则循环引用是一个(可解决的)问题.没有java实现使用引用计数,AFAIK.较新的Sun JRE使用多种类型的GC混合,我认为所有的标记和扫描或复制.
你可以在阅读一般更多关于垃圾收集维基百科,以及关于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一样快.