内存泄露简单来说就是一个对象已经无用了,但是还有引用存在并且是可达的,按照垃圾对象的判定那么JVM无法进行回收的,这种对象一直存在于应用程序的生命周期中,始终占用着内存。如果无法回收的对象过多就会影响系统的性能。导致内存泄露的场景主要有以下几种情况:
- 静态集合类:集合类比如HashMap、Vector等内部持有元素的引用,静态的话生命周期与应用程序相同,这会导致集合类内部的元素对象一直无法被回收,例如:
public class Main {
private static Vector vector = new Vector(15);
public static void main(String[] args) {
for (int i = 0; i < 15; i++) {
Object obj = new Object();
vector.add(obj);
obj = null; // 断开引用,虽然obj的引用被断开了,但是依然被Vector引用,会导致内存泄露
}
}
}
- 监听器:通常一个应用当中会用到很多监听器(Listener),但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。
- 单例模式:单例对象在初始化后将在 JVM 的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部的引用,那么这个对象将不能被 JVM 正常回收,导致内存泄漏。
- 各种连接:一般应用程序中存在各种连接,比如数据库连接、网络连接等,当应用程序结束之后要手动释放连接对象,如果不释放的话这些连接对象会依然存在,也会导致内存泄露。
- 内部类持有外部类的引用:如果内部类持有外部类的实例对象引用,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。
JProfiler
上文讲述了几种比较常见的导致内存泄露的情况,那如果发生了内存泄露我们该怎么去排查呢?如果有一款工具能够帮助我们分析就很方便了,JProfiler恰好就是这样一款分析内存泄露的优秀工具,JProfiler分析排查内存泄露请参考:jprofiler 查看程序内存泄露