如本文所述那么问题,循环引用管理得很好。
Java 不进行引用计数,它使用跟踪垃圾收集(例如标记和清除、复制集合或其某种组合)。如果遵循所有活动引用来找出哪些对象是“可访问的”,然后它会清理其他所有内容。
本身不可访问的对象中的引用不会影响可访问性,因此它们是否为 null 并不重要。
可以想象,将引用设置为 null 可能产生重大影响的唯一情况是在长时间运行的方法中丢弃非常大的对象。
在这种情况下,将图表的引用设置为 null 将有助于制作孤岛(即使对于内部循环引用)如本中所述article.
您将在以下位置找到有关无法访问状态的更多详细信息关于垃圾收集的真相:
无法到达
当对象不再存在强引用时,该对象将进入不可访问状态。
当一个对象不可访问时,它就成为收集的候选者。
注意措辞:
仅仅因为一个对象是收集的候选者并不意味着它会立即被收集
集。 JVM 可以自由地延迟收集,直到对象立即需要消耗内存为止。
需要注意的是,并非任何强引用都会在内存中保存对象。这些必须是从垃圾收集根链接的引用。 GC 根是一类特殊的变量,包括:
- (任何线程的)堆栈上的临时变量
- 静态变量(来自任何类)
- JNI 本机代码的特殊引用
循环强引用并不一定会导致内存泄漏。
考虑一段代码创建两个对象,并将它们分配给彼此的引用。
public void buidDog() {
Dog newDog = new Dog();
Tail newTail = new Tail();
newDog.tail = newTail;
newTail.dog = newDog;
}
在方法返回之前,存在来自临时堆栈变量的强引用buildDog
方法同时指向Dog
和Tail
.
之后buildDog
方法返回,则Dog
and Tail
两者都无法从根访问,并且成为收集的候选者(尽管虚拟机实际上可能不会无限期地收集这些对象)。