6:消除过期的对象引用
java 有自己的垃圾回收机制,当你用完一个对象之后,它会被自动回收,这看起来有点不可思议,并且很容易让你觉得你自己再也不需要考虑内存管理的事了。显然,这是一种错误的想法。
1. 过期引用
1.1 介绍
如果一个栈是先增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。这是因为,在栈内部维护着对这些对象的过期引用。
所谓的过期引用,是指永远也不会再被解除的引用。
1.2 修复
这类问题的修复很简单:一旦对象已经过期,只需要请看这些引用就好了:
public Object pop() {
if (size == 0) throw new EmptyStackException();
Object result = elements[--size];
elements[size] == null;
return result;
}
除了释放过期引用,清空过期引用的另一个好处是,如果它们以后又被错误的使用,程序就会立即抛出空指针异常,而不是让错误悄悄的潜下去。
1.3 注意
请空对象引用应该是一种例外而不是一种规范行为。消除过期引用最好的方法是让包含该引用的变量结束其生命周期。
一般而言,只要类是自己管理内存,那么就应该警惕内存泄漏问题。
2. 其他导致内存泄漏的原因
2.1 缓存。
一旦你把对象引用放到缓存中,他就很容易被遗忘掉,从而使得他不再被使用后的很长一段时间内仍然留在缓存中。
解决方案之一是,可以使用 WeakHashMap 代表缓存
只有当所需要的缓存项的生命周期是由该键的外部引用而不是值决定时,WeakHashMap 才有用处。
2.2 监听器和其回调
如果你实现了一个 API,客户端在这个 API 中注册回调,却没有显示的取消回调,那么除非你采取了某些动作,否则他们就会积聚。
确保回调被立即被当做垃圾回收的最佳方法是只把他们保存在弱引用中,例如,只将他们保存成 WeakHashMap 中的键。