Eliminate obsolete object references消除过期的对象引用
When you switch from a language with manual memory management, such as C or C++, to agarbage-collected language, your job as a programmer is made much easier by the fact that your objects are automatically reclaimed when you're through with them. It seems almost like magic when you first experience it. It can easily lead to the impression that you don't have to think about memory management, but this isn't quite true.
java中也要注意内存管理
// Can you spot the "memory leak"?
public class Stack {
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity) {
this.elements = new Object[initialCapacity];
}
Effective Java: Programming Language Guide
17
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size) {
Object[] oldElements = elements;
elements = new Object[2 * elements.length + 1];
System.arraycopy(oldElements, 0, elements, 0, size);
}
}
}
这里有一个内存泄漏
如果一个栈先是增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用(obsolete re f e re n c e)。所谓过期引用,是指永远也不会再被解除的引用
改正
public Object pop() {
if (size==0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference清除引用
return result;
}
当程序员第一次被类似这样的问题困扰的时候,他们往往会过分小心:对于每一个对象引用,一旦程序不再用到它,就把它清空。这样做既没必要,也不是我们所期望的,因为这样做会把程序代码弄得很乱,并且可以想像还会降低程序的性能。“清空对象引用”这样的操作应该是一种例外,而不是一种规范行为。消除过期引用最好的方法是重用一个本来已经包含对象引用的变量,或者让这个变量结束其生命周期。如果你是在最紧凑的作用域范围内定义每一个变量(见第2 9条),则这种情形就会自然而然地发生。应该注意到,在目前的J V M实现平台上,仅仅退出定义变量的代码块是不够的,要想使引用消失,必须退出包含该变量的方法。
一般而言,只要一个类自己管理它的内存,程序员就应该警惕内存泄漏问题。一旦一个元素被释放掉,则该元素中包含的任何对象引用应该要被清空。
内存泄漏的另一个常见来源是缓存。一旦你把一个对象引用放到一个缓存中,它就很容易被遗忘掉,从而使得它不再有用之后很长一段时间内仍然留在缓存中
posted on 2006-03-31 16:35
dodoma 阅读(199)
评论(0) 编辑 收藏 所属分类:
java基础