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

sal*_*sal 108 java performance garbage-collection

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

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

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

Nei*_*fey 70

这取决于您何时考虑使引用无效.

如果你有一个对象链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();
}
Run Code Online (Sandbox Code Playgroud)

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

  • 局部变量可以由机器优化。类变量不能。我已经看到(线程池上的)工作线程在处理请求后不会释放它们的状态对象,从而将这些对象固定在内存中,直到工作线程被赋予新任务(该任务立即用新任务覆盖了旧状态对象)。使用大型状态对象和数百个工作线程(例如:大型http服务器),这可能会保存并复制大量内存,但将永远不会再使用。 (2认同)

Chr*_*ung 25

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

请参阅Effective Java 2nd ed,Item 6:Eliminate Obsolete Object References.

  • @sal一般的经验法则是,如果你不能引用它,就会收集垃圾.因此,如果外部对象包含对另一个对象的引用,假设内部对象没有任何其他引用,则设置外部对象的引用并且仅引用null将导致整个对象被垃圾收集,包括其孤立引用. (7认同)
  • 这是一个"语义"问题.基本上,因为您已预先分配了一个数组,所以VM会看到它.它对容器的"逻辑"大小一无所知.假设您有一个大小为10的ArrayList,由16个元素的数组支持.VM无法知道项目10..15实际上没有使用; 如果这些插槽有内容,它们将不会被释放. (4认同)
  • 在你提到的同一个第6项中:**取消对象引用应该是例外,而不是标准.** (2认同)

Thi*_*ilo 10

实例字段,数组元素

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

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

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

范围变量:

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

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

{
  {  
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

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


bes*_*sen 5

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

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