geo*_*geo 19 java garbage-collection
让我们假设,有一个Tree对象,具有根TreeNode对象,并且每个TreeNode都有leftNode和rightNode对象(例如BinaryTree对象)
如果我打电话:
myTree = null;
Run Code Online (Sandbox Code Playgroud)
树中相关的TreeNode对象真的会发生什么?将垃圾收集,或者我必须设置树对象内的所有相关对象?
Ste*_*n C 33
Java中的垃圾收集是基于"可达性"执行的.JLS将术语定义如下:
"可到达的对象是任何可以从任何活动线程继续计算中访问的对象."
只要对象可以访问*,就不符合垃圾回收的条件.
JLS将其留给Java实现来确定如何确定对象是否可访问.如果实现不能确定,可以将理论上无法访问的对象视为可达...而不是收集它.(事实上,JLS允许实现不会收集任何东西!尽管如此,没有合理的实现会这样做.)
在实践中,(保守的)可达性通过追踪来计算; 通过以下从类(静态)变量开始的引用和线程堆栈上的局部变量来查看可以达到的内容.
以下是这对您的问题意味着什么:
如果我打电话:
myTree = null;
树内的相关TreeNode对象真的发生了什么?将垃圾收集,或者我必须设置树对象内的所有相关对象?
假设它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;
}
Run Code Online (Sandbox Code Playgroud)
在上面,我们知道如果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'
}
Run Code Online (Sandbox Code Playgroud)
一些Java编译器/运行时可能能够检测到循环结束后不需要'o',并将变量视为死.
*事实上,我们在这里谈论的是强大的可达性.当您考虑软,弱和幻像参考时,GC可达性模型会更复杂.但是,这些与OP的用例无关.
myTree
只是一个先前指向堆中对象的引用变量.现在您将其设置为null.如果您没有对该对象的任何其他引用,则该对象将有资格进行垃圾回收.
要让垃圾收集器删除对象,myTree
只需gc()
在设置之后进行调用null
myTree=null;
System.gc();
Run Code Online (Sandbox Code Playgroud)
请注意,仅当没有其他引用指向该对象时才会删除该对象.
归档时间: |
|
查看次数: |
23395 次 |
最近记录: |