Java 内存泄漏原因
- 长生命周期的对象持有短生命周期对象的引用:例如,静态集合不断添加对象而不清理
java
private static final List<byte[]> cache = new ArrayList<>();
void add() {
cache.add(new byte[1024 * 1024]);
}
- 未正确关闭资源:例如,数据库连接、文件流、网络连接未关闭
java
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("target.txt");
} catch (IOException e) {
e.printStackTrace();
}
- 内部类持有外部类引用:非静态内部类持有外部类实例,若内部类生命周期更长,会导致外部类无法释放
java
public class Outer {
private String value = "Outer";
class Inner {
void print() {
System.out.println(value);
}
@Override
protected void finalize() throws Throwable {
System.out.println("Inner 对象被回收");
super.finalize();
}
}
@Override
protected void finalize() throws Throwable {
System.out.println("Outer 对象被回收");
super.finalize();
}
}
java
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.print();
System.out.println("----- outer 被设置为 null");
outer = null;
System.gc();
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("----- inner 被设置为 null");
inner = null;
System.gc();
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
# 输出结果
Outer
----- outer 被设置为 null
----- inner 被设置为 null
Inner 对象被回收
Outer 对象被回收
-
不合理的作用域:将局部变量提升为静态变量,意外延长对象生命周期
-
监听器或回调未注销:注册了监听器或回调,但是缺少移除方法
-
ThreadLocal 使用不当:例如,线程池的线程复用时,ThreadLocal 未及时调用 remove 方法,导致数据残留