java内存泄漏主要因强引用阻止gc回收,典型场景包括:1.静态集合长期持有对象;2.非静态内部类隐式引用外部类;3.未关闭资源或threadlocal未remove。

内存泄漏在 Java 中通常指对象不再被使用,但垃圾回收器无法回收它,因为还存在强引用。最典型的演示方式是用静态集合长期持有对象引用,且不清理。
使用静态集合持续添加对象
静态变量生命周期与类相同,只要类加载后不卸载,其中的集合就一直存在。如果不断往静态 List 里 add 新对象,又不 remove,这些对象就永远无法被 GC。
- 定义一个静态 ArrayList
- 在循环中反复创建新对象并加入该列表
- 不提供清除逻辑,也不让引用失效
示例代码:
public class MemoryLeakDemo {
// 静态集合,长期持有对象引用
private static final List<object> cache = new ArrayList();
<pre class="brush:php;toolbar:false;">public static void main(String[] args) throws InterruptedException {
System.out.println("开始内存泄漏演示...");
for (int i = 0; i <p>}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/ai/1796" title="奇布塔"><img
src="https://img.php.cn/upload/ai_manual/000/000/000/175680366899415.png" alt="奇布塔" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/ai/1796" title="奇布塔" class="overflowclass">奇布塔</a>
<p class="overflowclass">一款面向有声绘本创作的AI工具,帮助用户围绕故事内容制作绘本和声音表现,降低儿童故事内容制作门槛。</p>
</div>
<a rel="nofollow" href="/ai/1796" title="奇布塔" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>内部类持有外部类引用导致泄漏
非静态内部类默认持有一个外部类的隐式引用。若内部类实例被静态变量或长生命周期对象(如线程池、监听器)持有,外部类也会被一起“钉住”,无法回收。
- 定义一个大对象(如含大量字段或缓存的类)
- 在其内部定义非静态 Runnable,并提交给静态线程池
- 该 Runnable 会间接持有外部类实例,造成泄漏
未关闭资源型对象(如未关闭的连接/流)
虽然严格来说属于资源泄漏,但某些场景下会导致关联对象(如缓冲区、句柄包装类)无法释放,间接引发堆内存增长。
- 用 FileInputStream 打开大文件但不调用 close()
- 使用 ThreadLocal 存储对象后未调用 remove(),尤其在线程池中复用线程时
如何验证是否发生泄漏
运行上述代码时加上 JVM 参数:-Xmx64m -XX:+PrintGCDetails,观察 Full GC 后老年代占用是否持续上升;也可用 VisualVM 或 JConsole 连接进程,查看堆内存曲线和对象实例数变化。










