将Java对象设置为null是否可以执行任何操作?

时间:2009-05-12 02:20:49

标签: java garbage-collection performance

我正在浏览一些旧书,并找到了Peter Hagger的“Practical Java”。在性能部分,建议在不再需要时将对象引用设置为null

在Java中,设置对null的对象引用是否可以提高性能或垃圾回收效率?如果是这样,在什么情况下这是一个问题?容器类?对象组成?匿名内部类?

我经常在代码中看到这一点。这是现在过时的编程建议还是仍然有用?

6 个答案:

答案 0 :(得分:69)

这取决于您何时考虑将引用置零。

如果你有一个对象链A-> B-> C,那么一旦A无法到达,A,B和C都有资格进行垃圾收集(假设没有其他东西指的是B或C) 。例如,没有必要,也从来没有任何需要明确地将参考A-> B或B-> C设置为null。

除此之外,大部分时间问题都没有真正出现,因为实际上你正在处理集合中的对象。您通常应该考虑通过调用适当的remove()方法从列表,地图等中删除对象。

曾经某些建议设置引用为null的情况特别是在长范围内,内存密集型对象不再在范围中途使用。例如:

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

这里的基本原理是因为 obj 仍在范围内,因此没有引用的显式归零,直到 doSomethingElse()之后它才会变为垃圾收集方法完成。这就是可能不再适用于现代JVM 的建议:事实证明,JIT编译器可以在不再使用给定本地对象引用的哪个点上运行。

答案 1 :(得分:25)

不,这不是过时的建议。悬空引用仍然是一个问题,特别是如果您使用预先分配的数组实现可扩展数组容器(ArrayList或类似物)。超出列表“逻辑”大小的元素应该被删除,否则它们将不会被释放。

参见Effective Java 2nd ed,Item 6:Eliminate Obsolete Object References。

答案 2 :(得分:10)

实例字段,数组元素

如果有对象的引用,则不能进行垃圾回收。特别是如果那个对象(以及它背后的整个图形)很大,那么只有一个引用可以阻止垃圾收集,并且不再需要该引用,这是一个不幸的情况。

病态案例是保留用于配置它的整个XML DOM树,未注册的MBean或从未部署的Web应用程序中阻止整个类加载器的对象的单一引用的对象从被卸下。

因此,除非你确定持有引用本身的对象无论如何都要进行垃圾收集(或者甚至那时),否则你应该将你不再需要的所有东西都归零。

范围变量:

如果您正在考虑在其范围结束之前将局部变量设置为null,以便垃圾收集器可以回收它并将其标记为“从现在开始无法使用”,则应考虑将其置于更多位置相反,范围有限。

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}

成为

{
  {  
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}

长而扁平的范围通常也不利于代码的易读性。为了这个目的而引入私人方法来解决问题并不是闻所未闻。

答案 3 :(得分:5)

在内存限制性环境(例如手机)中,这可能很有用。通过设置null,objetc不需要等待变量超出范围而被gc'd。

然而,对于日常编程,这不应该是规则,除非像Chris Jester-Young所引用的特殊情况那样。

答案 4 :(得分:1)

首先,它并不意味着您要将对象设置为null。我在下面解释一下:

List list1 = new ArrayList();
List list2 = list1;

在上面的代码段中,我们创建了存储在内存中的list1对象的对象引用变量名ArrayList。所以list1指的是那个对象,它只不过是一个变量。在第二行代码中,我们将list1的引用复制到list2。所以,如果我这样做,现在回到你的问题:

list1 = null;

这意味着list1不再引用存储在内存中的任何对象,因此list2也无需引用任何内容。因此,如果您检查list2的大小:

list2.size(); //it gives you 0

所以这里垃圾收集器的概念到了,它说«你没有什么可担心释放对象所拥有的内存,当我发现它将不再用于程序时我会这样做而JVM将会管理我。»

我希望它清楚这个概念。

答案 5 :(得分:0)

这样做的原因之一是消除过时的对象引用。 您可以阅读文字here.