null
在Java中分配未使用的对象引用是否以任何可测量的方式改进了垃圾收集过程?
我用Java语言(C#)的经验告诉我,经常是反直觉的,试图智取虚拟机或JIT编译器,但我已经看到同事用这个方法,我很好奇,如果这是一个很好的做法挑向上或那些巫术迷信编程的一个?
通常,没有.
但就像所有事情一样:这取决于.如今,Java中的GC非常好,所有内容都应该在不再可用后立即清理.这就是在为局部变量留下一个方法之后,以及当不再为字段引用类实例时.
如果您知道它将继续引用,则只需要显式为null.例如,保持在周围的阵列.您可能希望在不再需要数组的各个元素时将其置零.
例如,这个代码来自ArrayList:
public E remove(int index) { RangeCheck(index); modCount++; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; }
此外,只要没有引用仍然存在,显式地使对象无效将不会导致对象被收集的速度超过仅仅自然地超出范围的对象.
都:
void foo() { Object o = new Object(); /// do stuff with o }
和:
void foo() { Object o = new Object(); /// do stuff with o o = null; }
在功能上是等同的.
好文章是今天的编码恐怖.
GC的工作方式是查找没有任何指针的对象,搜索区域是堆/堆栈以及它们拥有的任何其他空间.因此,如果将变量设置为null,则实际对象现在不会被任何人指向,因此可能是GC'd.
但由于GC可能不会在那个确切的瞬间运行,你可能实际上并没有自己购买任何东西.但是如果你的方法相当长(就执行时间而言)可能是值得的,因为你将增加GC收集该对象的机会.
代码优化也会使问题变得复杂,如果在将变量设置为null后从不使用变量,则删除将值设置为null的行是一种安全的优化(少执行一条指令).所以你可能实际上没有得到任何改进.
总而言之,是的它可以提供帮助,但它不具有确定性.
根据我的经验,人们往往忽略偏执狂的引用并非必要.这是一个快速指南:
如果对象A引用对象B 并且您不再需要此引用,并且对象A不符合垃圾回收条件,那么您应该明确地将该字段置空.如果封闭对象无论如何都要收集垃圾,则无需将字段置空.在dispose()方法中取消字段几乎总是无用的.
无需在方法中创建对象引用.一旦方法终止,它们将自动清除.此规则的例外情况是,如果您运行的是非常长的方法或某个大型循环,则需要确保在方法结束之前清除某些引用.同样,这些案件极为罕见.
我会说绝大多数时候你不需要废除引用.试图超越垃圾收集器是没用的.您将最终得到效率低下,难以理解的代码.
至少在java中,它根本不是巫毒编程.使用类似的东西在java中创建对象时
Foo bar = new Foo();
你做两件事:首先,你创建一个对象的引用,第二,你创建Foo对象本身.只要该引用或其他引用存在,特定对象就不能被gc'd.但是,当您为该引用赋值null时...
bar = null ;
并假设没有其他任何东西有对该对象的引用,它在下次垃圾收集器经过时被释放并可用于gc.
这取决于.
一般来说,你保持对物体的引用越短,它们就越快被收集.
如果您的方法需要2秒钟才能执行,并且在方法执行一秒后不再需要对象,则清除对它的任何引用都是有意义的.如果GC在一秒钟后看到,您的对象仍然被引用,下次它可能会在一分钟左右检查它.
无论如何,默认情况下将所有引用设置为null对我来说是过早优化,没有人应该这样做,除非在特定的罕见情况下它可以显着减少内存消耗.
显式设置对null的引用而不仅仅是让变量超出范围,对垃圾收集器没有帮助,除非持有的对象非常大,一旦你完成就把它设置为null是一个好主意.
通常将引用设置为null,意味着该对象完全使用的代码的READER,并且不应再关注它.
通过添加一组额外的支架可以实现类似的效果
{
int l;
{ // <- here
String bigThing = ....;
l = bigThing.length();
} // <- and here
}
这允许bigThing在离开嵌套大括号后立即进行垃圾收集.
public class JavaMemory { private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6); public void f() { { byte[] data = new byte[dataSize]; //data = null; } byte[] data2 = new byte[dataSize]; } public static void main(String[] args) { JavaMemory jmp = new JavaMemory(); jmp.f(); } }
上面的程序抛出OutOfMemoryError
.如果你取消注释data = null;
,那就OutOfMemoryError
解决了.将未使用的变量设置为null始终是一种好习惯