1. 查看Tomcat日志定位泄漏线索
首先检查Tomcat的catalina.out、localhost.log等日志文件,重点查找OutOfMemoryError(如java.lang.OutOfMemoryError: Java heap space、Metaspace溢出)、频繁Full GC记录(如Full GC (System.gc()))或内存泄漏警告(如Tomcat自身对ThreadLocal泄漏的提示:The web application [app] created a ThreadLocal with key of type [java.lang.ThreadLocal] and a value of type [com.example.LogHelper] but failed to remove it when the web application was stopped)。这些信息能快速确认是否存在内存泄漏及大致方向。
2. 监控内存使用情况
使用jvisualvm(JDK自带)、jconsole或Linux下的top命令实时监控Tomcat进程的内存使用:
maxThreads配置),可能是线程池泄漏或线程未正确终止。3. 启用GC日志分析回收行为
在Tomcat启动脚本(如catalina.sh)中添加JVM参数,启用详细的GC日志:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log
通过GCViewer或GCEasy等工具解析日志,重点分析:
4. 生成并分析堆转储文件
当怀疑内存泄漏时,使用jmap命令生成堆转储快照(Heap Dump):
jmap -dump:format=b,file=/path/to/heapdump.hprof <Tomcat_PID>
或通过jcmd工具生成:
jcmd <Tomcat_PID> GC.heap_dump /path/to/heapdump.hprof
使用**Eclipse MAT(Memory Analyzer Tool)**打开堆转储文件,进行以下分析:
byte[]、HashMap);com.example.MyClass.staticList)。5. 代码审查与修复
根据堆转储分析结果,重点检查以下常见泄漏场景:
static Map)的生命周期与应用一致,若持续添加对象而不移除,会导致内存无限增长;ThreadLocal变量未在finally块中调用remove()方法,会导致线程复用时对象残留(如Tomcat线程池中的线程);Connection)、文件流(InputStream)、网络连接等未在finally块中关闭,导致资源对象无法被回收;6. 调整JVM参数优化
根据内存使用情况调整JVM参数,避免因配置不当加剧泄漏:
-Xms与-Xmx设为相同值,避免动态调整开销);-XX:MaxMetaspaceSize=256m,防止元空间溢出);-XX:+UseG1GC,适用于大内存应用,减少Full GC次数)。