java哪些错误的代码会导致内存泄漏?

经常听到和看到内存泄漏这个词,但是真的不是很明白或者怎么去避免出现内存泄漏这个问题呢?
做好是能从java方面分析

阅读 4k
6 个回答

不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:

复制代码 代码如下:

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...
}

显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况

首先,内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费。
一个Demo:
不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:

class A{ 
    public A(){ 
        B.getInstance().setA(this); 
    } 
.... 
} 

//B类采用单例模式 
class B{ 
    private A a; 
    private static B instance = new B(); 
    private B(){} 
    public static B getInstance(){ 
        return instance; 
    } 
    public void setA(A a){ 
        this.a=a; 
    } 
    ... 
} 

显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况

不一定是错误的代码。内存泄漏有可能是根本就忘了释放内存,也可能是未能及时释放内存。

举个极端的例子:

  1. A引用了 B,A.p = B,而且 A 的生命周期比较长;

  2. A引用B只使用了很短的一段时间,在A剩下的所有生命周期中,B都不再使用;

那个在 A 的整个生命周期中,B 一直存在,但有很长的一段时间是不使用的;此时 B 仍保持有引用,所以不会回收。在 A 的整个生命周期中,不再使用 B 的时候,B 就可以看作是内存泄漏了。在最极端的情况下,比如A的生命周期等于整个程序的生命周期,那么就会浪费内存了。

怎么避免呢?

  1. 在不需要使用之后,A 不要保留 B 的引用,如使用 A.p = null,那么 B 会在自己的生命周期结束后被回收;

  2. 合理设计,不要在 A 的整个生命周期中引用 B。

内存泄露:指的是程序在申请内存之后,没有办法释放掉已经申请到内存,它始终占用着内存,即被分配的对象可达但无用。内存泄露一般都是因为内存中有一块很大的对象,但是无法释放。

Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
    Object o=new Object();
    v.add(o);
    o=null;    
}

上面是个很简单的内存泄露例子,往集合中循环添加o对象100次。将o声明为null,其实并没有用,vectory中仍然有o对象的引用,这样GC就无法回收,就会引发内存泄露问题。要解决这个问题,还得o对象remove出去才可以解决!

静态变量容易内存泄漏,比如在内存中缓存一个静态的Map,里面放了很多信息,随着服务的不断运行,Map越来越大,然后就内存泄漏了,所以使用static变量的时候要考虑下数据量大概有多大

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题