单例模式容易引起内存泄露
不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:
- class A{
- public A(){
- B.getInstance().setA(this);
- }
- ....
- }
class A{
public A(){
B.getInstance().setA(this);
}
....
}
//B类采用单例模式
- class B{
- private A a;
- private static B instance=new B();
- public B(){}
- public static B getInstance(){
- return instance;
- }
- public void setA(A a){
- this.a=a;
- }
- //getter...
- }
class B{
private A a;
private static B instance=new B();
public B(){}
public static B getInstance(){
return instance;
}
public void setA(A a){
this.a=a;
}
//getter...
}
显然B采用singleton模式,他持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较大的对象或者集合类型会发生什么情况。
上面所讲的这些也启发我们如何去查找内存泄露问题,第一选择当然是利用工具,比如jprofiler,第二就是在代码复审的时候关注长生命周期对象:全局性的集合、单例模式的使用、类的static变量等等。