有一个广泛的对象图的应用程序.该图主要由通过唯一参考连接到图的其余部分的一组子图组成.但是内部每个这样的子图具有一些对象之间的交叉引用.有一段时间,这样的一个子图需要抛弃.是否只能设定将唯一的引用指向该子图以使其符合垃圾收集资格的足够?
我的关注是,内部交叉引用可能会“保护”整个子图避免垃圾回收.换句话说,垃圾收集器是否足够明白,以确定子图中的所有引用不会离开子图的边界,因此可以清除整个子图.
解决方法
如本
SO question所述,循环参考文献管理良好.
Java不做引用计数,它做“标记和扫描”垃圾收集.如果遵循所有的活动参考,找出什么对象是“可达到的”,然后清理所有其他的东西.
对象本身可以访问的引用不会影响可达性,所以如果它们为空,则不重要.
关于设置对null的引用的唯一情况可能会有意义的是在长时间运行的方法的中间丢弃一个非常大的对象.
在这种情况下,将null设置为图形的引用将有助于形成隔离岛(即使是内部循环引用),如本article所述.
您将在The Truth About Garbage Collection中找到有关无法访问状态的更多详细信息:
无法访问
当没有更强的引用存在时,对象进入不可达到的状态.
当一个对象无法访问时,它是一个候选人.
注意措辞:
只是因为一个对象是收藏的候选人并不意味着它会立即
集. JVM可以自由延迟收集,直到需要立即需要对象使用的对象.
重要的是要注意,不只是强有力的参考将在内存中占有一个对象.这些必须是从垃圾回收根链接的引用. GC根是一个特殊类的变量,包括:
>栈上的临时变量(任意线程)
>静态变量(来自任何类)
> JNI本机代码的特殊参考
循环强引用不一定会导致内存泄漏.
考虑一个创建两个对象的代码,并将它们分配给彼此的引用.
public void buidDog() { Dog newDog = new Dog(); Tail newTail = new Tail(); newDog.tail = newTail; newTail.dog = newDog; }
在方法返回之前,buildDog方法中的临时堆栈变量有很强的引用,指向“狗”和“尾”.
在buildDog方法返回后,Dog和Tail都从根目录无法访问,并且是收集的候选项(尽管VM可能无法实时收集这些对象无限期的时间).