Effective Java 的笔记,代码、英语原文为主,批注、翻译为辅。
Item 7: Eliminate obsolete object references
消除过时的对象引用
Incorrect Version
一个简单的Stack实现的例子:
|
|
那么是哪里出现了“内存泄漏”的问题呢?请认真思考🤔。
提示:在pop()
方法里,也可以和Java源码比较发现这个隐蔽的问题。
So where is the memory leak? If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack maintains
obsolete references
to these objects.An obsolete reference is simply a reference that will never be dereferenced again
. In this case, any references outside of the “active portion” of the element array are obsolete. The active portion consists of the elements whose index is less than size.
Memory leaks in garbage-collected languages (more properly known as unintentional object retentions) are insidious. If an object reference is
unintentionally retained
, not only is that object excluded from garbage collection, but so too areany objects referenced by that object
, and so on. Even if only a few object references are unintentionally retained, many, many objects may be prevented from being garbage collected, with potentially large effects on performance.
Corrected Version
The fix for this sort of problem is simple:
null out references once they become obsolete
. In the case of our Stack class, the reference to an item becomes obsolete as soon as it’s popped off the stack. The corrected version of the pop method looks like this:
|
|
An added benefit of nulling out obsolete references is that if they are subsequently dereferenced by mistake, the program will immediately fail with a
NullPointerException
, rather than quietly doing the wrong thing.It is always beneficial to detect programming errors as quickly as possible.
Java source code
Stack类的pop()方法:
|
|
查看removeElementAt(int index)方法:
|
|
可以看到elementData[elementCount] = null; /* to let gc do its work */
没想到源码的注释这么详细,从源码中学习。
When should you null out a reference?
不过作者也提到了Nulling out object references should be the exception rather than the norm.
So when should you null out a reference? What aspect of the Stack class makes it susceptible to memory leaks? Simply put,
it manages its own memory
. The storage pool consists of the elements of the elements array (the object reference cells, not the objects themselves). The elements in the active portion of the array (as defined earlier) are allocated, and those in the remainder of the array are free.The garbage collector has no way of knowing this; to the garbage collector, all of the object references in the elements array are equally valid.
Only the programmer knows that the inactive portion of the array is unimportant. The programmer effectively communicates this fact to the garbage collector by manually nulling out array elements as soon as they become part of the inactive portion.
只要类是自己管理内存,程序员就应该警惕内存泄漏问题。
Generally speaking, whenever a class manages its own memory, the programmer should be alert for memory leaks. Whenever an element is freed, any object references contained in the element should be nulled out.