温馨提示×

Tomcat日志中内存溢出怎么解决

小樊
31
2025-12-15 16:25:56
栏目: 智能运维

Tomcat 内存溢出定位与解决

一、先快速定位 OOM 类型

  • 查看 catalina.outlocalhost..log 中的异常关键字,常见有:
    • Java heap space:堆内存不足,对象分配失败。
    • PermGen space:永久代不足(主要发生在 Java 7 及更早)。
    • Metaspace:元空间不足(Java 8+ 使用元空间替代永久代)。
    • unable to create new native thread:无法创建新线程,多与系统/容器资源限制有关。
  • 示例命令:tail -n 200 $CATALINA_HOME/logs/catalina.out | grep -i “OutOfMemoryError”。根据异常类型选择对应处理路径。

二、对应类型的处理要点

  • Java heap space
    • 增大堆内存:设置 -Xms-Xmx(建议等值,如 -Xms2g -Xmx2g),避免频繁扩容与回收抖动。
    • 选择合适的 GC:如 G1 GC(示例:-XX:+UseG1GC),并结合业务停顿目标调参。
    • 分析堆转储:在发生 OOM 时导出 heap dump 并用 MAT/VisualVM 定位泄漏对象与根引用链。
  • PermGen space(Java 7-)
    • 增大永久代:-XX:PermSize=… -XX:MaxPermSize=…(如 128m/256m)。
    • 减少类加载与热部署频率,清理无用依赖与重复 jar。
  • Metaspace(Java 8+)
    • 限制元空间上限:-XX:MaxMetaspaceSize=…(如 256m/512m),防止无界增长。
    • 排查动态生成类(反射、字节码增强、热部署)与类加载器泄漏。
  • unable to create new native thread
    • 检查系统/容器限制:如 ulimit -u(用户进程数)、ulimit -n(文件句柄);必要时调大。
    • 降低 Tomcat 线程压力:在 server.xml 中合理设置 maxThreads、acceptCount,避免线程风暴。

三、JVM 参数与 server.xml 示例

  • 设置堆与元空间(Linux,编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 前添加;Windows 用 catalina.bat 的 set JAVA_OPTS)
    • Java 8+ 示例:
      • JAVA_OPTS=“-Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC”
    • Java 7 示例:
      • JAVA_OPTS=“-Xms2g -Xmx2g -XX:PermSize=128m -XX:MaxPermSize=256m”
  • 线程与连接(示例,按负载调整)
  • 建议在 JAVA_OPTS 中开启 GC 日志,便于事后分析(示例):
    • -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log。

四、验证与长期治理

  • 重启后在日志中确认参数生效(ps -ef | grep tomcat 或进程环境变量),并用 jstat -gc 观察 YGC/FGC 频率与耗时;必要时用 VisualVM/JConsole 做在线观测。
  • 发生 OOM 时导出并分析 heap dump(如 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=…),用 MAT 查找泄漏根因并修复代码/配置。
  • 预防建议:
    • 合理设置 -Xms/-Xmx(如不超过物理内存的约 1/4),避免盲目增大;
    • 控制依赖与类加载数量,减少热部署频率;
    • 优化 maxThreads/acceptCount 与后端连接池,避免资源争用;
    • 建立监控与基线(GC、线程、内存、响应时延),异常及时告警。

0