后端高频问题
# 如何排查(定位)内存泄漏问题
内存泄漏:不再需要的对象引用,依然存在于堆内存中,垃圾收集器无法删除他们。出现原因可能有:
- 长声明周期对象持有短生命周期对象的引用
- 流这样的资源没被及时关闭
- 没有正确使用缓存 ThreadLocal
首先,我认为定位内存泄漏问题,需要看是什么系统,什么场景,因为不同的系统或场景,会影响我们定位内存泄漏的步骤和思路。
其次,以linux下的应用程序为例,我的一般解决思路是:
- 使用pss监控进程的实际内存占用情况,确定内存泄漏存在。
- 泄漏存在,对代码进行静态扫描,解决所有扫描出来的问题。
- 使用内存检测工具,如valgrind,memchecker,解决工具检测出的问题。
- 使用内存分析调试工具,比如C/C++的mtrace,或者java程序的 VisualVM、jconsole、jmap、jstat ,解决定位出的问题。
其中,我以jconsole为例,更加详细的向您说明下定位步骤:
- 使用jconsole连接到java应用程序,建立连接后,可以查看 堆内存和非堆内存的使用情况,对象数量和大小,以及垃圾回收的情况。
- 观察内存使用情况随时间的变化。如果发现内存占用持续增长,可能意味着依然存在内存泄漏问题。
- jconsole 会生成堆转储文件 heap dump,其中包含了应用程序运行时的堆内存中的对象信息。通过分析这些转储文件,找出哪些对象占用了大量内存,并且分析它们的引用链是如何形成的。
- 根据 dump 文件和内存使用情况, 定位导致内存泄漏的代码。通常,这涉及到查找未正确释放的对象引用或者长期存在的对象引用导致无法被垃圾回收的情况。
- 定位到具体的问题代码后,尝试修复并重新启动测试应用程序。
最后,再次进行测试后,如果依然存在内存泄漏问题,我认为很有可能是应用程序的特性,可以加点内存条,根据具体业务场景或需求按时重启。