【发布时间】:2010-10-15 09:33:33
【问题描述】:
在 java 中什么情况下显式置空有用。它是否以任何方式通过使对象无法访问或其他方式来帮助垃圾收集器?这被认为是一种好的做法吗?
【问题讨论】:
标签: java
在 java 中什么情况下显式置空有用。它是否以任何方式通过使对象无法访问或其他方式来帮助垃圾收集器?这被认为是一种好的做法吗?
【问题讨论】:
标签: java
在 Java 中,如果您有一个运行时间很长的方法,它可以提供帮助,并且对对象的唯一引用是通过局部变量。当您不再需要该局部变量时将其设置为 null(但当该方法将继续运行很长时间时)可以帮助 GC。 (在 C# 中,这很少有用,因为 GC 会考虑“最后可能的使用”。这种优化可能会在一段时间内用于 Java - 我不知道。)
同样,如果您有一个引用对象的成员字段并且您不再需要它,您可以通过将该字段设置为 null 来帮助 GC。
然而,根据我的经验,做这些事情很少实际上有用,而且它使代码更加混乱。很少有方法真的会运行很长时间,而将变量设置为 null 确实与您希望方法实现的目标无关。当您不需要时这样做不是一个好习惯,如果您确实需要,您应该首先查看重构是否可以改善您的设计。 (可能是你的方法或类型做的太多了。)
请注意,将变量设置为 null 完全是被动的 - 它不会通知垃圾收集器该对象可以被收集,它只是避免垃圾收集器将该引用视为下次保持对象活动的原因( GC) 运行。
【讨论】:
通常不需要它(当然这可能取决于 VM 实现)。但是,如果你有这样的事情:
private static final Map<String, String> foo;
然后在地图中有您不再需要的项目将不符合垃圾收集条件,因此您需要明确删除它们。有很多这样的情况(事件侦听器是另一个可能发生这种情况的领域)。
但是做这样的事情:
void foo()
{
Object o;
// use o
o = null; // don't bother doing this, it isn't going to help
}
编辑(忘了提这个):
如果你使用它,你会发现你声明的 90-95% 的变量都可以是 final 的。 final 变量不能改变它指向的东西(或者它的原始值)。在大多数情况下,如果一个变量是 final 的,那么在方法执行时它接收到不同的值是一个错误(错误)。
如果你希望能够在使用后将变量设置为null,则它不能是最终的,这意味着你有更大的机会在代码中创建错误。
【讨论】:
我发现它很有用的一个特殊情况是当您有一个非常大的对象并想用另一个大对象替换它时。比如看下面的代码:
BigObject bigObject = new BigObject();
// ...
bigObject = new BigObject(); // line 3
如果 BigObject 的实例太大以至于堆中只能有一个这样的实例,第 3 行将失败并出现 OutOfMemoryError,因为在第 3 行中的赋值指令完成之前无法释放第一个实例,这显然是在第二个实例已准备就绪。
现在,如果您在第 3 行之前将 bigObject 设置为 null:
bigObject = null;
bigObject = new BigObject(); // line 3
在构造第二个实例的过程中,当 JVM 用完堆时,可以释放第一个实例。
【讨论】:
来自“Effective Java”:用它来消除过时的对象引用。否则会导致内存泄漏,很难调试。
public Object pop(){
if(size == 0)
throw new EmptyStatckException();
Object result = elements[--size];
elements[size] = null; //Eliminate Object reference
return result;
}
【讨论】:
elements[size] == null AFTER 你已经减小了大小?
elements[0] 存储了一个元素。元素作为结果缓存,数组中的位置无效,导致堆栈大小为 0。
如果您在方法块关闭时将一个即将超出范围的对象清空,那么在垃圾收集方面没有任何好处。遇到不理解这一点的人,他们非常努力地将很多东西设置为不必要的空,这并不罕见。
【讨论】:
另请参阅 J2SE 中的 WeakReference。
【讨论】:
在满足以下所有条件的极少数情况下,显式置空有助于 GC:
实际上,这在好的代码中是非常罕见的:如果不再需要该对象,您通常应该在更窄的范围内声明它。例如,如果您只需要在单个方法调用期间使用该对象,则它应该是一个局部变量,而不是封闭对象中的一个字段。
显式归零真正有用的一种情况:如果使用 null 来指示特定状态,那么设置为 null 值有时是必要且有用的。 Null 本身就是一个有用的值,原因如下:
【讨论】: