内存泄漏(Memory Leak)是面试中经常被问到的问题,也是长期运行服务最头疼的隐患之一。简单说,程序运行时申请了一块内存,用完却没有释放,这块内存就一直被占着,别人也没法用。下面结合几张图把它的原理、后果和避免方法一次讲清楚。

内存泄漏是怎么发生的?
程序每运行一次,都会从内存管理的视角出发,向内存池拿走一块内存,正常情况下用完归还。但如果某一次忘记归还,这块内存就成了“泄漏的内存块”。随着运行次数增加,泄漏块会越来越多。常见原因包括:忘记释放、对象一直被引用、缓存没有上限地增长、集合不断添加元素从不清理。一次泄漏可能不明显,但不断积累后,可用内存会越来越少。

用酒店退房来理解内存泄漏
把内存想象成酒店房间:申请内存=开房,使用内存=入住,释放内存=退房。如果客人已经走了,但前台系统没有办理退房,房间明明没人,却无法给其他客人使用。内存泄漏就是这么回事。

有 GC 的语言也会内存泄漏吗?
很多人以为有垃圾回收(GC)的语言不会内存泄漏,答案是:会。GC 能自动回收没有任何引用的对象,但如果一个对象已经没有实际用途,却仍然被 List、Map、缓存或静态变量引用,GC 就会认为它还在使用,不会回收。对象没用了不等于 GC 一定会回收,只要无用对象一直被引用,就可能发生内存泄漏。

内存泄漏会造成什么后果?
内存泄漏通常不会立刻让程序崩溃,而是随着运行时间不断积累。刚开始内存池大部分是空的,运行一段时间后被占用格子增多,长期运行后几乎全被占满。内存占用越来越高,程序越来越慢,最终可能 OOM。长期运行的服务尤其需要注意。

如何避免内存泄漏?
避免内存泄漏的核心原则是:该释放的及时释放,该清理的及时清理。具体来说:集合不要无限增加,及时移除不再使用的元素;缓存要设置过期时间,定期清理;对象不再使用时及时解除引用;必要时使用内存分析工具检测定位问题。同时还要注意集合大小、缓存数据、静态变量和长期引用等细节。

内存泄漏是每个开发者都绕不开的话题,不管是像 C/C++ 这样手动管理内存,还是依赖 GC,理解它的成因和避免方法都能让你在排查性能问题时更有方向。在面试中回答这类问题时,能结合内存池、酒店退房类比以及 GC 的盲区,通常会让面试官点头。更多技术讨论,欢迎到云栈社区一起交流。
|