什么是Java中的过时参考

时间:2019-02-09 18:04:15

标签: java

  

我正在阅读《有效的Java》一书,它的一句话是消除过时的引用是避免内存泄漏的最佳方法之一。根据以下程序,通过执行-> elements [size] = null;它消除了该程序中的过时引用。   我的问题是做elements [size] = null;有什么好处。任何其他程序都可以使用该释放的内存位置吗?还是收集垃圾?   根据我的理解,数组已经为其大小分配了内存。即使我们做elements [size] = null;除非您执行elements = null ;,否则任何人都无法使用该释放的内存位置。请有人告诉我做elements [size] = null;有什么好处?在这里。

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
}

3 个答案:

答案 0 :(得分:2)

  

我的问题在这里,做elements [size] = null;的好处是什么。

这里过时的引用是指程序不再需要的对象引用。
您希望那些不必要的对象可以自由地仅消耗程序所需的内存。通常,这样做是为了使当前应用程序正常运行。

  

任何其他程序都可以使用释放的内存位置吗?

理论上可以,但是还取决于所使用的JVM内存选项。您通常不会专注于此。

elements[size] = nullelements = null;完全没有相同的意图和相同的效果。

在书中,elements是类的结构实习生。
想法是,在执行某些删除操作后,阵列的某些元素可能已过时,不再需要。

如果没有其他对象引用,则第一个(elements[size] = null)将使位于size索引处的数组元素的对象有资格成为GC。
但是第二个(elements = null)还有更多。如果没有其他对象引用该数组,则它将使该数组的所有元素都有资格成为GC。

答案 1 :(得分:1)

我们必须区分两种情况:

  1. 外部对象以某种方式被“破坏”了,因此它关闭了所有打开的资源,并“自愿地”释放了它所引用的所有对象。这只是告诉jvm相应引用已“消失”的明确方法。您可以使gc更容易理解:相应的对象可以进行垃圾回收。当然,只有在其他地方没有其他引用同一对象的情况下,该功能才会起作用。不仅如此:并非真正需要这样做,jvm / gc当然必须能够自行检测所有合格对象。
  2. 但对于存在较长时间的引用(在该时间段内指向不同的对象),将其设为空是有意义的。就像容器一样,例如基础示例中的堆栈类。容器必须忘记“删除”了它所引用的对象。否则会造成内存泄漏!

答案 2 :(得分:0)

这里会发生什么?

让我们想象一下,elements是一个包含20个元素的Object数组(elements = new Object[20];),并已填充了18个BigInteger实例,其余两个位置为空。

因此,堆现在包含18个BigInteger实例和20个元素的Object[]数组。垃圾回收器不会回收这些实例中的任何一个,这没关系,因为您以后很可能会使用它们(通过pop()方法)。

现在,您调用pop()方法以获取最近添加到数组的BigInteger。假设您只想打印然后忘记它,因此在您的整个应用程序中,不再需要该数字,并且您希望垃圾回收器可以回收它。但是除非您执行空分配,否则不会发生

elements[size] = null; // Eliminate obsolete reference

为什么?

只要将对对象的引用存储在某个可访问的位置,垃圾收集器就会认为您以后仍然需要该对象。

只要elements[17]仍然引用BigInteger,程序就可以访问它,因此无法对其进行回收。如果elements[17]指向null,则以前无法通过BigInteger进行访问的elements可以被垃圾收集器回收(如果您的代码的其他部分仍然没有用)使用它。)

结论

如果您有一个包含胖对象的长寿存储结构,并且可以在某个时间点告诉您不再需要其中一个存储对象,那么仅值得考虑“过时引用”。由于您不再需要该对象,因此现在可以使用null重新分配存储,然后GC不再认为您仍然需要该对象,并且可以回收存储空间。