首先需要确认内存溢出的具体类型(如堆内存、元空间、线程耗尽等),这是解决问题的关键。
catalina.out(位于TOMCAT_HOME/logs/)或localhost.log,寻找OutOfMemoryError相关错误信息(如java.lang.OutOfMemoryError: Java heap space、java.lang.OutOfMemoryError: Metaspace)。jconsole、jvisualvm(JDK自带)或Eclipse MAT(堆转储分析工具)实时监控内存使用情况,定位内存泄漏点(如持续增长的对象占用)。jmap命令生成堆转储文件,再用jhat或Eclipse MAT分析,找出占用内存最多的对象(如未关闭的数据库连接、静态集合中的大量数据)。根据诊断结果,调整Tomcat的JVM启动参数,优化内存分配。需修改TOMCAT_HOME/bin/catalina.sh(Linux下)文件,在文件开头或echo "Using CATALINA_BASE"上方添加以下参数:
Java heap space溢出):export JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx2048m"
-Xms:初始堆内存(建议与-Xmx一致,避免频繁扩容);-Xmx:最大堆内存(不超过服务器物理内存的80%,如16GB内存可设为-Xmx12g)。Metaspace溢出,Java 8及以上版本):export JAVA_OPTS="$JAVA_OPTS -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
PermGen(永久代),Metaspace默认无大小限制,但需根据应用动态加载类的情况调整。export JAVA_OPTS="$JAVA_OPTS -XX:NewSize=512m -XX:MaxNewSize=1024m"
-XX:NewSize:年轻代初始大小;-XX:MaxNewSize:年轻代最大大小(建议为堆内存的1/3~1/2)。export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
G1GC(Garbage-First Garbage Collector)比传统CMS更适合大内存应用,可通过-XX:MaxGCPauseMillis设置最大GC停顿时间(如-XX:MaxGCPauseMillis=200)。内存溢出的根本原因往往是代码中的内存泄漏或不合理的对象使用,需针对性优化:
try-with-resources语句确保资源释放;ThreadLocal变量(如在finally块中调用threadLocal.remove()),避免线程复用导致的对象残留;static Map中缓存大量数据),及时清理无用数据。new String()、new ArrayList()),尽量重用对象;Caffeine、Ehcache等缓存框架设置maximumSize),避免缓存无限增长;TTL),定期清理过期数据。除JVM参数外,Tomcat自身的配置也会影响内存使用:
unable to create new native thread溢出):conf/server.xml中的Connector配置,增加最大线程数和等待队列长度:<Connector port="8080" protocol="HTTP/1.1"
maxThreads="500" <!-- 最大线程数(默认200,根据并发量调整) -->
minSpareThreads="50" <!-- 最小空闲线程数 -->
acceptCount="200" <!-- 等待队列长度(默认100,队列满会拒绝请求) -->
connectionTimeout="20000" />
protocol参数(如org.apache.coyote.http11.Http11NioProtocol),提升高并发下的性能。若应用需要更高的内存或并发支持,需调整操作系统参数:
Too many open files问题):
ulimit -n 65535(当前会话有效);/etc/security/limits.conf,添加以下内容(针对tomcat用户):tomcat hard nofile 65535
tomcat soft nofile 65535
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
可将这些命令添加到/etc/rc.local中,开机自动生效。内存溢出问题可能反复出现,需建立持续监控机制:
jstat监控GC情况(如jstat -gcutil <pid> 1000,每秒输出一次GC统计信息),或Prometheus+Grafana搭建可视化监控平台,跟踪内存使用趋势。JMeter、Selenium等工具模拟高并发场景,测试Tomcat在极限负载下的内存表现,提前发现问题并调整参数。通过以上步骤,可系统性解决Linux环境下Tomcat的内存溢出问题。需根据实际应用场景(如内存泄漏类型、并发量、服务器配置)灵活调整参数,优先修复代码中的内存泄漏,再优化JVM和系统配置。