如何解决Ubuntu上Tomcat内存溢出
导读:Ubuntu上Tomcat内存溢出的定位与解决 一、快速判断与定位 查看 /opt/tomcat/logs/catalina.out 或 logs/catalina.out 中的异常关键字: Java heap space:堆内存不足;...
Ubuntu上Tomcat内存溢出的定位与解决
一、快速判断与定位
- 查看 /opt/tomcat/logs/catalina.out 或 logs/catalina.out 中的异常关键字:
- Java heap space:堆内存不足;
- PermGen space(JDK 7 及更早):永久代不足;
- Metaspace(JDK 8+):元空间不足;
- unable to create new native thread:线程数触达系统或容器上限。
- 快速确认当前 JVM 参数与内存使用:
- 获取进程号:pid=$(ps -ef | grep tomcat | grep -v grep | awk ‘{ print $2} ’)
- 堆与元空间:jmap -heap $pid
- GC 概况:jstat -gcutil $pid 1000 30
- 线程与系统限制:top -H -p $pid、ulimit -a、必要时用 lsof -n | awk ‘{ print $2} ’ | sort | uniq -c | sort -nr | head 查看打开文件数。
- 若看到 PermGen/Metaspace 报错,多半是应用加载类过多(如热部署、大量第三方 JAR、JSP 预编译);若老年代长期打满并频繁 Full GC,通常是堆设置偏小或存在内存泄漏。
二、常见根因与对应措施
- 堆内存不足(Java heap space)
- 现象:GC 频繁、老年代占用接近 100%、吞吐下降。
- 处理:适度提升 -Xms/-Xmx,并配合合理的年轻代与 GC 策略;必要时做内存泄漏排查。
- 永久代/元空间不足(PermGen/Metaspace)
- 现象:部署/热更新后很快 OOM,或类加载器泄漏。
- 处理:JDK 7 增加 -XX:PermSize/-XX:MaxPermSize;JDK 8+ 增加 -XX:MetaspaceSize/-XX:MaxMetaspaceSize;清理无用依赖与重复 JAR,避免频繁热部署。
- 线程数触顶(unable to create new native thread)
- 现象:高并发下线程创建失败。
- 处理:优化 server.xml 线程池与连接器参数,避免线程风暴;同时检查 ulimit -u(用户进程数)与 open files(文件句柄)限制。
- 文件句柄耗尽
- 现象:访问变慢或失败,伴随“打开文件数”远超限制。
- 处理:提升 ulimit -n,排查连接泄漏与日志/临时文件未关闭等问题。
- 系统资源不足
- 现象:物理内存或交换空间紧张。
- 处理:扩容内存或优化应用内存占用。
三、配置与优化步骤
- 调整 JVM 内存参数(示例,按机器内存与负载调整)
- JDK 8+ 示例(在 $CATALINA_HOME/bin/catalina.sh 的合适位置添加,如 “# OS specific support” 之前):
- 建议将 -Xms 与 -Xmx 设为相同,减少堆扩展带来的抖动:
- 一般应用:
- JAVA_OPTS=“-server -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -Xss256k -Djava.awt.headless=true”
- 大内存/高并发:
- JAVA_OPTS=“-server -Xms4g -Xmx4g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -Xss256k -Djava.awt.headless=true”
- 一般应用:
- 建议将 -Xms 与 -Xmx 设为相同,减少堆扩展带来的抖动:
- JDK 7 及更早(使用 PermGen):
- JAVA_OPTS=“-server -Xms2g -Xmx2g -XX:PermSize=256m -XX:MaxPermSize=512m -Xss256k -Djava.awt.headless=true”
- 说明:
- -server 启用服务器模式;
- -Xms/-Xmx 为堆初始/最大值;
- -XX:MetaspaceSize/-XX:MaxMetaspaceSize(JDK 8+)或 -XX:PermSize/-XX:MaxPermSize(JDK 7-)控制元空间/永久代;
- -Xss 控制线程栈大小(过高会占用更多内存、过低可能栈溢出);
- 不建议把 -Xmx 超过物理内存,且应预留给系统与其他进程。
- JDK 8+ 示例(在 $CATALINA_HOME/bin/catalina.sh 的合适位置添加,如 “# OS specific support” 之前):
- 优化 Tomcat 线程与连接(server.xml)
- 使用共享线程池并合理设置:
- 要点:避免过高的 maxThreads 与过长的队列(acceptCount),结合压测找到拐点。
- 使用共享线程池并合理设置:
- 系统层面检查与调整
- 提升文件句柄与进程数限制(/etc/security/limits.conf 或 systemd 服务 LimitNOFILE/LimitNPROC),并确认 ulimit -n/-u 已生效;
- 监控 open files 与线程数,防止句柄/线程泄漏。
四、验证与监控
- 重启后在日志中确认参数已生效(如:ps -ef | grep tomcat 应能看到 -Xms/-Xmx/-XX:MetaspaceSize 等);
- 观察 jmap -heap $pid 的堆与元空间配置是否到位;
- 用 jstat -gcutil $pid 1000 30 观察 YGC/YGCT、FGC/FGCT、老年代使用率 是否趋于稳定;
- 若老年代仍长期接近 100% 并频繁 Full GC,优先排查内存泄漏(对象生命周期、缓存、会话/静态集合、第三方库),再考虑进一步扩容或优化 GC 策略。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 如何解决Ubuntu上Tomcat内存溢出
本文地址: https://pptw.com/jishu/787405.html
