在C/C++中,变量(或对象)的生命周期可以由程序员通过new/malloc和delete/free自行控制,若发生内存泄漏,一般认为是程序员代码编写有漏洞,而在java中内存由系统管理,但并不表示java就不会发生内存泄漏,只是表现的形式略有不同罢了。
java中内存泄漏的原因为:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收。
举个经典的例子
Vector v = new Vector(10);
for (int i = 1; i<100; i++)
{Object o = new Object();
v.add(o);
o = null;
}
代码中对象o已经置null了,但依然无法被gc回收,因为变量v引用这些对象。除非将o移出v或者将v置null。
可能产生内存泄漏的几个场景
1.静态/全局集合类
像HashMap、Vector等集合类的使用容易出现内存泄露,这些静态/全局的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,最好的做法是将不需要的对象移出集合类,这里也要注意移出失败的情况,比如集合里面的对象属性被修改了。
2.各种对象池
对象池的使用可以提高系统的运行效率,因而广泛使用在java程序中,一般对象池都有申请对象和释放对象两个操作,而往往容易遗忘是就是申请了对象,却没有及时的释放,导致对象被长期占有而引起内存泄漏。
3.单例模式
单例模式的初始化之后,对象是以静态变量的形式存在,如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露。
还有哪些情况可能导致内存泄漏,我先抛砖引玉,大家可以多多跟帖,互相学习。