温馨提示×

Tomcat在Linux如何解决内存溢出

小樊
32
2025-12-20 20:03:38
栏目: 智能运维

Linux下Tomcat内存溢出定位与解决

一、快速定位与日志确认

  • 查看 Tomcat 日志tail -f **/path/to/tomcat/logs/catalina.out**,优先确认异常类型(堆、元空间、线程等)与时间点。
  • 检查 JVM 进程与参数ps -ef | grep tomcat,核对实际生效的 -Xms/-Xmx/-XX:PermSize/-XX:MaxPermSize 等值。
  • 排查 系统资源限制ulimit -a(关注 open filesmax user processesvirtual memory 等),必要时提升限制,避免“资源不足”伪装成内存问题。
  • 若表现为“运行一段时间变慢或无法访问”,优先检索 catalina.out 中的 OutOfMemoryError 关键字,结合时间点与近期变更定位诱因。

二、按异常类型调整JVM参数

  • 常见三类异常与对应处置要点如下(注意区分 Java 7/8Java 8+ 的元空间差异):
异常类型 典型触发 关键参数(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
  • Linux 修改位置与示例(catalina.sh):在 cygwin=false 这一行之前添加(注意引号为英文双引号):
    • Java 7 示例:
      JAVA_OPTS="-Xms1024m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m"
    • Java 8+ 示例:
      JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=512m"
      修改后重启 Tomcat 并校验进程参数是否生效。

三、系统层面与Tomcat配置优化

  • 提升系统限制(示例):
    • 临时:ulimit -n 65536(文件句柄)、ulimit -u 65536(进程数)
    • 永久:在 /etc/security/limits.conf 为运行 Tomcat 的用户添加如:
      • tomcat soft nofile 65536
      • tomcat hard nofile 65536
      • tomcat soft nproc 65536
      • tomcat hard nproc 65536
  • 优化 Tomcat 线程与连接(server.xml):
    • 使用共享线程池并合理设置:
      • <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"/>
    • 目的:以更少的线程支撑更多连接,降低线程创建压力与内存占用。

四、监控、验证与代码侧治理

  • 打开 GC 日志 便于分析:
    • 示例:-verbose:gc -Xloggc:/opt/tomcat/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
    • 结合日志观察 Full GC 频率、晋升失败、元空间/堆使用曲线,指导参数微调。
  • 验证与回放:
    • 重启后在日志中确认参数生效(ps -ef | grep tomcat),并压测/回放业务高峰,观察 catalina.outgc.log 是否复现 OOM。
  • 代码与架构侧治理(治本):
    • 排查 类加载器泄漏(热部署/多应用隔离不当)、静态集合膨胀大对象长期持有未关闭资源(流/连接/会话)、递归过深 等。
    • 控制依赖与重复 JAR,减少 PermGen/Metaspace 压力;优化缓存策略(大小、过期、弱引用/软引用)。

0