当Tomcat日志中出现OOM(Out of Memory)错误时,通常表示Java虚拟机无法分配足够的内存资源,导致应用程序崩溃或性能下降。以下是一些解决和预防Tomcat OOM问题的步骤:
快速诊断步骤
- 检查日志文件:
- 查看
catalina.out和localhost.log文件,寻找OutOfMemoryError、StackOverflowError或线程死锁信息。
- 监控资源使用:
- 实时查看内存和CPU使用情况:
top -p $(pgrep -f tomcat)
- 检查线程数:
ps -eLf | grep tomcat | wc -l
常见原因及解决方案
1. 内存不足(OOM)
- 现象:
java.lang.OutOfMemoryError: Java heap space - 解决方法:
- 调整JVM内存参数(在
setenv.sh中设置):
export JAVA_OPTS="-Xms512m -Xmx1024m -XX:MaxMetaspaceSize=256m"
- 建议:
Xms和Xmx设为相同值避免动态调整开销。- 不超过系统物理内存的70%。
2. 线程池耗尽
- 现象:
java.util.concurrent.TimeoutException或请求卡死 - 解决方法:
- 修改
conf/server.xml的Connector配置:
<Connector
executor="tomcatThreadPool"
maxThreads="200" <!-- 默认200,根据负载调整 -->
minSpareThreads="20"
acceptCount="100" <!-- 等待队列长度 -->
/>
- 监控线程使用:
jstack $(pgrep -f tomcat) | grep "http-nio" | wc -l
3. 应用内存泄漏
- 排查工具:
- 生成堆转储文件分析:
jmap -dump:format=b,file=/tmp/heap.hprof $(pgrep -f tomcat)
- 使用
jvisualvm或Eclipse MAT分析泄漏对象。 - 常见泄漏源:
- 静态集合未清理、未关闭的数据库连接、第三方库Bug。
4. 文件描述符耗尽
- 现象:
Too many open files - 解决方法:
- 检查限制:
ulimit -n
- 修改系统限制(
/etc/security/limits.conf):
tomcat soft nofile 65535
tomcat hard nofile 65535
5. 数据库连接池问题
- 排查:
- 检查连接池配置(如
maxActive是否过高)。 - 监控数据库连接泄漏:
SHOW STATUS LIKE 'Threads_connected';
高级排查工具
- JVM监控
- 使用
jstat观察GC情况:
jstat -gcutil $(pgrep -f tomcat) 1000
- 频繁Full GC(
FGC列高)表明内存问题。
- 线程转储分析
- 生成线程转储:
kill -3 $(pgrep -f tomcat) # 输出到catalina.out
- 使用
fastthread.io在线分析死锁。
预防措施
- 定期检查和优化应用代码:
- 确保没有内存泄漏,及时释放资源。
- 使用监控工具:
- 实时监控Tomcat和JVM的性能指标,及时发现并解决问题。
通过以上步骤,可以有效地诊断和解决Tomcat日志中的OOM问题,并采取措施预防未来的发生。