静态集合类易致内存泄漏,因其生命周期与JVM一致,若无意识持有对象引用(如Activity、Context),则对象无法被GC回收;应优先用WeakHashMap、提供显式清理方法、避免存局部对象,并用VisualVM定位。
为什么静态集合类容易引发内存泄漏
静态变量的生命周期与JVM相同,如果静态集合(如
、
)无意识地持有对象引用,这些对象就无法被GC回收,哪怕业务逻辑早已结束。常见于缓存、监听器注册表、单例管理器等场景。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
优先用
替代
存储缓存项,键为弱引用,GC时自动清理失效条目
若必须用强引用集合,务必配套提供显式清理方法(如
),并在业务退出点调用
避免将局部对象(尤其是Activity、Fragment、Context)直接放入静态集合——Android中极易导致OOM
使用
或
的“OQL”查询静态字段引用链,快速定位泄漏源头
内部类持有外部类引用导致的泄漏怎么破
非静态内部类(包括匿名类,如
、
)隐式持有所在外部类实例的引用。若该内部类对象被长期持有(如线程池中的任务、Handler消息队列里的
),外部类(比如一个Activity)就无法释放。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
将内部类改为
,并通过弱引用来访问外部状态:
Android开发中,不要在Activity中直接 new
;改用
并确保 Runnable 不捕获 this
使用
(Kotlin)或
回调替代手动管理异步任务生命周期
检查日志中是否频繁出现
—— 这是典型的内部类泄漏信号
资源未关闭引发的堆外内存泄漏怎么查
Java中
、
、
、
、
等对象背后常关联堆外内存或系统资源。未显式
会导致这些资源长期驻留,JVM无法自动回收,尤其在高并发或长连接场景下会迅速耗尽内存。
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
所有实现
的资源,一律用 try-with-resources 语法:
数据库连接必须走连接池(如 HikariCP),禁用
直连;并确认连接池配置了
和
Netty 或 NIO 应用中,检查
是否被正确
;未释放的
会堆积在
中
用
查看
和
区域持续增长,大概率指向未释放的 native 资源
如何验证内存泄漏是否真正修复
光看代码逻辑不够,必须通过可观察的行为确认效果。GC日志、堆快照、对象计数变化才是最终依据。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
启动JVM时加上:
,观察 Full GC 后老年代占用是否持续上升
用
对比多次调用前后的对象数量,重点关注业务类、Listener、Callback 实例是否只增不减
触发一次
,用 Eclipse MAT 打开,按 “Leak Suspects” 报告和 “Dominator Tree” 排序,找 Retained Heap 最大的非基础类
在线上环境慎用 dump;可用
采样堆分配热点:
,定位高频 new 的泄漏源头
真正难的不是发现泄漏,而是确认某个对象“本该被回收却没被回收”的因果链——这要求你清楚知道它的生命周期边界在哪里,而不仅仅是盯着 GC 日志看数字。
static Mapstatic ListWeakHashMapHashMapclearCache()VisualVMJProfilernew Thread(Runnable)new Handler()RunnablestaticWeakReference ref = new WeakReference<>(this); Handler()Handler(Looper.getMainLooper())lifecycleScope.launch { ... }LifecycleAware"leaked Activity" or "FinalizerReference"InputStreamOutputStreamConnectionResultSetByteBufferclose()AutoCloseabletry (FileInputStream fis = new FileInputStream(...)) { ... }DriverManager.getConnection()maxLifetimeidleTimeoutByteBufrelease()PooledByteBufPoolThreadCachejcmd VM.native_memory summary InternalOther-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.logjmap -histo:live jmap -dump:format=b,file=heap.hprof async-profiler./profiler.sh -e alloc -d 30 -f alloc.html 