清理过期的对象引用

清理过期的对象引用

概述

在使用具备垃圾自动回收功能的编程语言时,可能会对不需要手动管理内存感到不可思议,以为不再需要考虑内存管理的事情。其实不然

例子

如果一个程序使用栈的时候先增长,后收缩,那么弹出来的对象将不会被当作垃圾回收,这是栈对对象的过期引用,虽然下标已经发生了改变,但对象应用却被无意识地保留了起来。

要解决这个问题,可以清空这些引用即可:

1
2
3
4
5
6
public Object pop() {
if (size == 0) throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null;
return result;
}

这样做还有一个好处,一旦被错误地引用,会抛出NullPointerException。

注意

  • 清空对象引用应该是一种例外,而不是一种规范行为;
  • 只要类是自己管理内存的,程序员应该警惕内存泄漏问题

内存泄漏来源

  1. 缓存

如果对象引用被放到缓存中,很可能被遗忘掉,以至于很长一段时间内都留在缓存中;

比如好的解决方法是用WeakHashMap代表缓存,但只有当所要的缓存项的生命周期是由key的外部引用而不是value决定时,才有用。tomcat的源码里,实现缓存时会用到WeakHashMap

  1. 监听器和其他回调

客户端在Api中注册了回调,却没有显式地取消回调。那么这时最好的解决方法是,将它们保存为WeakHashMap的key,即保存它们的弱引用。