Tomcat在Linux环境下运行时,内存溢出(OutOfMemoryError)是常见问题,主要表现为JVM无法为对象分配足够内存。解决该问题需结合日志诊断、JVM参数调整、代码优化及系统配置等多方面处理,以下是具体步骤:
解决内存溢出的第一步是明确溢出类型,需通过日志和工具定位具体原因:
catalina.out或应用日志,寻找OutOfMemoryError相关错误信息(如Java heap space、PermGen space、Metaspace、unable to create new native thread等),这是定位问题的核心线索。jconsole、jvisualvm(JDK自带)或VisualVM等工具,实时监控Tomcat的内存使用情况(堆内存、元空间、线程数等),观察内存增长趋势。jmap命令生成堆转储文件(jmap -dump:format=b,file=heap.hprof <pid>),再用Eclipse MAT(Memory Analyzer Tool)分析,查找占用内存最多的对象(如未释放的集合、缓存等),定位内存泄漏点。根据诊断结果,调整Tomcat的JVM参数以优化内存分配,参数需在catalina.sh(Tomcat/bin目录下)文件开头添加:
Java heap space溢出,设置初始堆大小(-Xms)和最大堆大小(-Xmx),建议将两者设为相同值(避免堆内存动态扩展的开销),且不超过物理内存的80%(如物理内存16GB,可设为-Xms8g -Xmx8g)。PermGen space溢出(Java 8之前)或Metaspace溢出(Java 8及以上),需替换对应参数:
-XX:PermSize=256m -XX:MaxPermSize=512m(永久代初始/最大大小);-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m(元空间初始/最大大小,避免类加载过多导致溢出)。-Xmn)大小,通常设为堆内存的1/4(如-Xmx8g则-Xmn2g),提升新生代对象的回收效率。-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log,记录垃圾回收详情,帮助分析GC频率和耗时,进一步优化内存配置。内存溢出的根本原因往往是代码问题,需针对性优化:
String拼接用StringBuilder代替+),降低GC压力。DBCP、HikariCP、ThreadPoolExecutor)重用,避免重复创建和销毁。InputStream、Connection、ThreadLocal等资源在使用后及时关闭(用try-with-resources或finally块),防止内存泄漏。ThreadLocal(在finally中调用remove()方法),防止对象无法被GC回收。操作系统层面的限制可能加剧内存溢出,需同步调整:
unable to create new native thread错误。通过ulimit -n 65535临时调整,或在/etc/security/limits.conf中永久设置(如* soft nofile 65535、* hard nofile 65535)。/etc/sysctl.conf,优化内存管理(如vm.swappiness=10降低交换分区使用,vm.dirty_ratio=20控制脏页刷新频率),提升系统内存利用率。内存溢出问题需持续监控,避免复发:
tail -f catalina.out或日志分析工具(如ELK),实时监控OutOfMemoryError的出现情况。JMeter、Selenium等工具模拟高并发场景,评估Tomcat在峰值负载下的内存使用情况,提前调整JVM参数。通过以上步骤,可系统性解决Linux环境下Tomcat的内存溢出问题。需注意的是,调整JVM参数需结合服务器硬件配置和应用实际负载,避免过度分配内存导致系统资源紧张。