温馨提示×

Ubuntu Tomcat内存不足怎么办

小樊
42
2025-12-22 23:13:48
栏目: 智能运维

Ubuntu 下 Tomcat 内存不足的排查与优化

一、先快速定位问题类型

  • 查看 Tomcat 日志:重点关注 logs/catalina.outlogs/startup.loglogs/localhost.log,从异常栈和 GC 信息判断是堆内存、元空间、线程栈还是系统内存不足。
  • 观察异常关键词:
    • Java heap space → 堆内存不足;
    • PermGen space(Java 7 及更早)→ 永久代不足;
    • Metaspace(Java 8+)→ 元空间不足;
    • 出现 “There is insufficient memory for the Java Runtime Environment to continue”“Cannot allocate memory”“Cannot create GC thread” → 多为系统物理内存或 swap 不足、或线程/句柄等资源限制导致。
  • 检查系统资源:
    • 内存与交换分区:free -hswapon -s
    • 线程与句柄:ulimit -aps -eLf | wc -l
    • 端口占用:ss -lntp | grep ':8080\|:8005'
      以上步骤能快速确定是“JVM 参数过小”还是“系统资源瓶颈”。

二、针对不同错误类型调整配置

  • 堆内存不足(Java heap space)
    • 适度提升堆上限:将 -Xms-Xmx 设为相同值以减少 GC 波动,例如:-Xms2g -Xmx2g(请结合机器内存与容器/虚拟机配额)。
  • 元空间不足(Metaspace,Java 8+)
    • 增加元空间上限:-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m(避免无限制增长)。
  • 永久代不足(PermGen,Java 7 及更早)
    • 增加永久代:-XX:PermSize=128m -XX:MaxPermSize=256m
  • 线程栈溢出(StackOverflowError)
    • 减少单线程栈深度:-Xss256k(默认通常为 1M,视应用而定)。
  • 系统层面内存不足(无法提交内存、无法创建 GC 线程)
    • 先减小 -Xmx、降低线程数(见下一节)、减少应用加载的 Class/依赖;
    • 增加物理内存或开启/扩大 swap
    • 放宽系统限制:如 ulimit -n 65535(文件描述符)、ulimit -u 65535(用户进程数),并在 /etc/security/limits.conf 持久化;
    • 确认使用 64 位 Java + 64 位 OS
      这些参数与系统侧调整能分别解决不同层面的“内存不足”。

三、在 Ubuntu 正确设置 Tomcat 的 JVM 参数

  • 通用方式(适用于多数安装方式):编辑 $CATALINA_HOME/bin/catalina.sh,在文件靠前位置加入(或导出)变量:
    • Java 8 示例:
      • export JAVA_OPTS="-server -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -Xss256k"
    • Java 7 示例:
      • export JAVA_OPTS="-server -Xms2g -Xmx2g -XX:PermSize=128m -XX:MaxPermSize=256m -Xss256k"
    • 如需 GC 日志便于排查,可追加:
      • -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/opt/tomcat/logs/gc.log
  • Debian/Ubuntu 包管理安装的 Tomcat(如 tomcat7/tomcat8/tomcat9):优先编辑 /etc/default/tomcatX(X 为版本号),在该文件中设置或追加 JAVA_OPTS,例如:
    • JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
  • 使配置生效并重启:
    • 包管理安装:sudo systemctl restart tomcatX
    • 解压版:$CATALINA_HOME/bin/shutdown.sh && $CATALINA_HOME/bin/startup.sh
  • 验证是否生效:
    • ps -ef | grep tomcat | grep -E 'Xms|Xmx|Metaspace|PermSize' 应能看到你设置的参数。
      以上路径与方式覆盖“解压版”和“deb 包安装版”的主流做法,避免改错文件导致配置不生效。

四、应用与容器的配套优化建议

  • 控制并发与线程栈:在 conf/server.xml 中结合业务调优,例如:
    • <Connector port="8080" protocol="HTTP/1.1" maxThreads="200" minSpareThreads="50" acceptCount="250" enableLookups="false" URIEncoding="UTF-8" />
    • 线程数减少可直接降低内存压力(每个线程会占用栈空间)。
  • 减少常驻对象与类加载:清理无用依赖、避免在应用启动阶段加载大体积库、关闭开发期功能(如热加载、自动部署)。
  • 开启并定期分析 GC 日志:观察 Full GC 频率、晋升失败、元空间占用增长趋势,据此微调堆与元空间。
  • 资源隔离:若在同一台机器运行多个实例,合理分配每个实例的 -Xmx 与线程数,避免“总和超过物理内存”。
    这些优化能显著降低内存压力并提升稳定性。

五、常见坑位与快速修复清单

  • -Xmx 设得过大导致系统无法分配内存或无法创建 GC 线程:先降低到机器可承受范围,再逐步上调;必要时增加 swap 或扩容。
  • 32 位 Java/系统导致地址空间受限:改用 64 位 Java + 64 位 OS
  • 文件描述符/进程数限制过低:在 /etc/security/limits.conf 提升 nofilenproc,并重启会话或系统服务。
  • 包安装版改了 catalina.sh 却无效:应修改 /etc/default/tomcatX 中的 JAVA_OPTS
  • 启动闪退但看不到错误:前台运行 ./catalina.sh run 或查看 catalina.out,优先从日志定位。
    以上为高频根因与对应处理,能快速排除环境与配置层面的“坑”。

0