Linux下Tomcat内存溢出定位与解决
一、快速定位与日志确认
tail -f **/path/to/tomcat/logs/catalina.out**,优先确认异常类型(堆、元空间、线程等)与时间点。ps -ef | grep tomcat,核对实际生效的 -Xms/-Xmx/-XX:PermSize/-XX:MaxPermSize 等值。ulimit -a(关注 open files、max user processes、virtual memory 等),必要时提升限制,避免“资源不足”伪装成内存问题。二、按异常类型调整JVM参数
| 异常类型 | 典型触发 | 关键参数(Linux catalina.sh 中的 JAVA_OPTS) | 备注 |
|---|---|---|---|
| Java heap space | 对象过多、缓存膨胀、大文件/批量处理 | -Xms 与 -Xmx 设为相同,如 -Xms2g -Xmx2g;可按需设置新生代 -Xmn(如约为 -Xmx 的 1/4) |
建议不超过物理内存的70%~80%,避免与系统和其他进程争用 |
| PermGen space(Java 7 及以前) | 类/类加载器泄漏、JSP 预编译、依赖 JAR 多 | -XX:PermSize=… -XX:MaxPermSize=…,如 -XX:PermSize=256m -XX:MaxPermSize=512m |
Java 8 起已废弃,改用 Metaspace |
| Metaspace(Java 8+) | 同上,但发生在元空间 | 移除 PermSize/MaxPermSize;新增 -XX:MaxMetaspaceSize=…,如 -XX:MaxMetaspaceSize=512m | 默认无上限,建议设置上限并结合监控 |
| unable to create new native thread | 线程数过多、栈过大、系统/容器限制 | 降低 -Xmx 或 -Xss,减少线程栈占用;提升 ulimit -u(max user processes)与 -n(open files);优化应用并发模型 | 线程上限估算:(MaxProcessMemory − JVMMemory − ReservedOsMemory) ÷ ThreadStackSize |
JAVA_OPTS="-Xms1024m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m"JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=512m"三、系统层面与Tomcat配置优化
ulimit -n 65536(文件句柄)、ulimit -u 65536(进程数)tomcat soft nofile 65536tomcat hard nofile 65536tomcat soft nproc 65536tomcat hard nproc 65536<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="20" maxIdleTime="60000"/><Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="30000" keepAliveTimeout="15000" maxKeepAliveRequests="100" enableLookups="false" acceptCount="100"/>四、监控、验证与代码侧治理
-verbose:gc -Xloggc:/opt/tomcat/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStampsps -ef | grep tomcat),并压测/回放业务高峰,观察 catalina.out 与 gc.log 是否复现 OOM。