让我们假设,有一个Tree对象,有一个根TreeNode对象,每个TreeNode都有leftNode和rightNode对象(例如BinaryTree对象)
如果我打电话:
myTree = null;
树中相关的TreeNode对象真的发生了什么?将垃圾收集,或者我必须设置树对象内的所有相关对象?
答案 0 :(得分:32)
Java中的垃圾收集是基于“可达性”执行的。 JLS将术语定义如下:
“可访问的对象是任何可以从任何活动线程继续计算中访问的对象。”
只要对象可以访问 * ,就不符合垃圾回收的条件。
JLS将其留给Java实现来弄清楚如何确定对象是否可以可访问。如果实现不能确定,可以将理论上无法访问的对象视为可达...而不是收集它。 (实际上,JLS允许实现不收集任何东西!尽管如此,没有合理的实现会这样做。)
在实践中,(保守的)可达性是通过追踪来计算的;通过以下从类(静态)变量开始的引用和线程堆栈上的局部变量来查看可以达到的内容。
以下是您的问题的含义:
如果我调用:
myTree = null;
树内相关的TreeNode对象会发生什么?也会被垃圾收集,或者我必须在树对象中设置null所有相关对象??
假设myTree
包含对树根的最后剩余可到达引用。
null
。)null
分配给对内部节点的引用是错误的。您正在拆除其他人可能稍后尝试使用的数据结构。)如果myTree
不包含最后剩余可访问树根的引用,则归零内部引用是错误的,原因与在3.上面。
那么应该你null
什么东西来帮助垃圾收集器呢?
您需要担心的情况是您何时可以确定某个单元格(本地,实例或类变量或数组元素)中的引用不会再次使用,但是编译器和运行时不能!案件大致分为三类:
仍在范围内的局部变量中的对象引用...但不会被使用。例如:
public List<Pig> pigSquadron(boolean pigsMightFly) {
List<Pig> airbornePigs = new ArrayList<Pig>();
while (...) {
Pig piggy = new Pig();
...
if (pigsMightFly) {
airbornePigs.add(piggy);
}
...
}
return airbornePigs.size() > 0 ? airbornePigs : null;
}
在上面,我们知道如果pigsMightFly
为false,则不会使用列表对象。但是,预计没有主流的Java编译器可以解决这个问题。
实例变量或数据结构不变量的数组单元格中的对象引用意味着它们不会被使用。 @ edalorzo的堆栈示例就是一个例子。
应该注意的是,编译器/运行时有时会发现范围内的变量实际上已经死了。例如:
public void method(...) {
Object o = ...
Object p = ...
while (...) {
// Do things to 'o' and 'p'
}
// No further references to 'o'
// Do lots more things to 'p'
}
某些Java编译器/运行时可以能够检测到循环结束后不需要'o',并将变量视为死。
*事实上,我们在这里讨论的是强大可达性。当您考虑软,弱和幻像参考时,GC可达性模型会更复杂。但是,这些与OP的用例无关。
答案 1 :(得分:5)
myTree
只是一个先前指向堆中对象的引用变量。现在您将其设置为null。如果您没有对该对象的任何其他引用,那么该对象将有资格进行垃圾回收。
要让垃圾收集器删除对象myTree
,只需在将gc()
设置为null
后调用myTree=null;
System.gc();
{{1}}
请注意,只有在没有其他引用指向它时才会删除该对象。
答案 2 :(得分:4)
除非您有其他参考(可能是手动),否则它们将被垃圾收集。如果您只是引用了树,那么是的,它们将被垃圾收集。
答案 3 :(得分:4)
您不能将对象设置为null
,只能设置一个可能包含指向此对象的指针/引用的变量。对象本身不受此影响。但是,如果现在没有从任何生命线程(即任何正在运行的方法的局部变量)到您的对象的路径存在,那么如果需要内存,它将被垃圾收集。这适用于任何对象,也适用于原始树对象引用的对象。
请注意,对于局部变量,如果方法(或块)无论如何都会很快完成,通常不必将它们设置为null
。
答案 4 :(得分:1)
在Java中,您不需要将对象显式设置为null
以允许它们进行GC。当没有对它的引用时,对象符合GC的条件(忽略java.lang.ref.*
类)。
答案 5 :(得分:0)
当没有对象的引用时,会收集对象。
在您的情况下,将收集由myTree
(根节点)正式引用的对象直接引用的节点,依此类推。
如果您对树之外的节点有出色的引用,那么当然不是这种情况。一旦这些引用超出范围(以及只有它们引用的任何内容),这些将得到GC。