温馨提示×

Linux下Tomcat内存溢出怎么办

小樊
44
2025-12-05 00:28:50
栏目: 智能运维

Linux下Tomcat内存溢出定位与处理

一、快速判断异常类型

  • 查看 catalina.outlocalhost.<日期>.log 中的异常关键字,常见三类:
    • Java heap space:堆内存不足,通常是对象申请过多且未及时释放。
    • PermGen space / Metaspace:类元数据区不足,常见于应用热部署频繁、第三方 jar 多或版本冲突。
    • unable to create new native thread:系统无法再创建线程,多与系统/容器内存与线程栈配置相关。

二、对应处理方案

  • 堆内存不足(Java heap space)
    • 调整堆大小:设置 -Xms-Xmx(建议等值,如 -Xms2g -Xmx2g),并结合 -Xmn(常取 -Xmx 的 1/4)优化新生代;总堆一般不超过物理内存的 80%。示例:JAVA_OPTS=“-Xms2g -Xmx2g -Xmn512m”。
  • 元空间不足(PermGen/Metaspace)
    • Java 7 及更早:增大 -XX:PermSize-XX:MaxPermSize(如 -XX:PermSize=256m -XX:MaxPermSize=512m)。
    • Java 8 及以后:使用 -XX:MetaspaceSize-XX:MaxMetaspaceSize(如 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m),避免无限制增长。
  • 无法创建新线程(unable to create new native thread)
    • 估算最大线程数:线程上限 ≈ (MaxProcessMemory − JVMMemory − ReservedOsMemory) / ThreadStackSize。例如 32 位进程可用约 2GB、JVM 占用 1.5GB、系统保留 120MB、默认线程栈 1MB/线程,则上限约 380 线程;可通过降低 -Xmx、减小 -Xss、或增加系统可用内存来提升上限。
  • 系统资源与容器配置
    • 检查 ulimit -a(如 open filesmax user processes),必要时调大;排查应用是否打开过多文件句柄或创建过多线程。

三、在Linux中修改Tomcat内存参数

  • 编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 这一行之前添加 JAVA_OPTS(注意引号为英文双引号):
    • Java 7 示例:
      • JAVA_OPTS=“-Xms1024m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m”
    • Java 8+ 示例:
      • JAVA_OPTS=“-Xms1024m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m”
  • 如使用服务方式启动,需按服务脚本/工具(如 systemd 单元或 Tomcat 自带服务包装器)的文档设置 JAVA_OPTS 或相应服务参数,避免仅修改 catalina.sh 不生效。

四、验证与监控

  • 重启后在日志中确认参数已生效(如 ps -ef | grep tomcat 能看到带 -Xms/-Xmx 的 Java 进程),并观察 catalina.out 是否仍有 OOM。
  • 打开 GC 日志以辅助分析:添加 -verbose:gc -Xloggc:gc.log,必要时配合可视化工具(如 jvisualvm)或堆转储分析(如 Eclipse MAT)定位大对象与泄漏根因。

五、常见陷阱与优化建议

  • -Xms-Xmx 设为相同,减少运行时扩缩堆带来的抖动;-Xmn 常取 -Xmx 的 1/4,其余留给老年代。
  • 减少 jar 冲突/重复:将通用第三方 jar 放到 tomcat/shared/lib(适用于多应用共享场景),降低 PermGen/Metaspace 压力。
  • 控制线程与连接:避免线程泄漏与连接泄漏;必要时优化 Connector/Executor 线程池配置,减少不必要的线程创建。

0