副标题 / 摘要
Java 有 GC 也会出现内存泄漏。本文用经典栈实现解释为什么对象引用没清理会导致泄漏。
目标读者
- 使用 Java 的开发者
- 关注内存问题的工程师
- 需要理解引用机制的人
背景 / 动机
GC 只能回收“不可达对象”。
如果引用没清理,哪怕对象不再需要,也不会被回收。
核心概念
- 对象可达性:决定是否可回收
- 引用残留:对象仍被数组引用
- 逻辑泄漏:对象不再使用却无法回收
实践指南 / 步骤
- 识别不再使用的引用
- 在 pop 后显式置空
- 使用工具分析堆快照
- 写回归测试验证
可运行示例
import java.util.EmptyStackException;
import java.util.Arrays;
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0) throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // 防止内存泄漏
return result;
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
解释与原理
数组中残留的引用使对象仍然“可达”。
显式置空可以让 GC 回收对象。
常见问题与注意事项
GC 不会自动清理吗?
GC 只处理不可达对象。这种泄漏常见吗?
在缓存、集合中非常常见。如何排查?
用堆快照工具(MAT、VisualVM)。
最佳实践与建议
- 对可变集合及时清理引用
- 对缓存设置过期机制
- 定期做内存分析
小结 / 结论
Java 内存泄漏多来自“引用未清理”。
理解可达性是避免泄漏的关键。
参考与延伸阅读
- Effective Java: Item 7
- Java Memory Leak Guide
元信息
- 阅读时长:6~8 分钟
- 标签:内存管理、Java
- SEO 关键词:Java 内存泄漏, 引用清理
- 元描述:解释 Java 栈实现中的内存泄漏。
行动号召(CTA)
检查你的缓存或集合是否清理引用,避免逻辑泄漏。