我正在阅读《有效的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;
}
答案 0 :(得分:2)
我的问题在这里,做elements [size] = null;的好处是什么。
这里过时的引用是指程序不再需要的对象引用。
您希望那些不必要的对象可以自由地仅消耗程序所需的内存。通常,这样做是为了使当前应用程序正常运行。
任何其他程序都可以使用释放的内存位置吗?
理论上可以,但是还取决于所使用的JVM内存选项。您通常不会专注于此。
elements[size] = null
和elements = null;
完全没有相同的意图和相同的效果。
在书中,elements
是类的结构实习生。
想法是,在执行某些删除操作后,阵列的某些元素可能已过时,不再需要。
如果没有其他对象引用,则第一个(elements[size] = null
)将使位于size
索引处的数组元素的对象有资格成为GC。
但是第二个(elements = null
)还有更多。如果没有其他对象引用该数组,则它将使该数组的所有元素都有资格成为GC。
答案 1 :(得分:1)
我们必须区分两种情况:
答案 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不再认为您仍然需要该对象,并且可以回收存储空间。