如何解决Ubuntu Tomcat内存溢出问题
导读:Ubuntu 上 Tomcat 内存溢出的定位与解决 一、先快速定位 OOM 类型与触发点 查看 $CATALINA_HOME/logs/catalina.out 与 localhost.log*,根据异常关键字判断类型: Java h...
Ubuntu 上 Tomcat 内存溢出的定位与解决
一、先快速定位 OOM 类型与触发点
- 查看 $CATALINA_HOME/logs/catalina.out 与 localhost.log*,根据异常关键字判断类型:
- Java heap space:堆内存不足,常见于大数据量、缓存或大对象。
- PermGen space(JDK 7 及更早):永久代/元空间不足,常见于热部署、加载大量类/JAR。
- Metaspace(JDK 8+):元空间不足,类加载过多或类加载器泄漏。
- unable to create new native thread:线程数触顶,常与连接数、线程栈设置相关。
- 用系统命令确认进程与资源:
- 查进程:ps -ef | grep java
- 看内存概要:jmap -heap
- 看 GC 与内存代:jstat -gcutil 1000 30
- 看线程与 CPU 占用:top -H -p ;定位占用最高线程后用 printf “%x\n” 转 16 进制,再用 jstack | grep -A 30 查栈。
二、针对性解决步骤
- 堆内存不足(Java heap space)
- 适度提升堆上限,建议 -Xms 与 -Xmx 设为相同,避免运行期扩缩带来的抖动;结合物理内存与容器/系统占用,一般不超过可用内存的 70%–80%。
- 示例(放到 catalina.sh 的合适位置):JAVA_OPTS=“$JAVA_OPTS -Xms2g -Xmx2g”。
- 永久代/元空间不足(PermGen/Metaspace)
- JDK 7 及更早:增加 -XX:PermSize=… -XX:MaxPermSize=…。
- JDK 8+:使用 -XX:MetaspaceSize=… -XX:MaxMetaspaceSize=…(不设上限有风险,建议显式上限)。
- 减少重复加载:将通用 JAR 放到 $CATALINA_HOME/shared/lib(或对应版本的解压目录结构),降低 Perm/Metaspace 压力。
- 线程耗尽(unable to create new native thread)
- 降低单线程栈:-Xss256k(默认通常较大,适当减小可创建更多线程,但过小会栈溢出)。
- 合理控制并发:在 conf/server.xml 的 中调优 maxThreads(并发处理线程数)、acceptCount(排队队列长度)、connectionTimeout(超时)等参数,避免无界排队与线程风暴。
三、在 Ubuntu 正确设置 JVM 参数
- 编辑 $CATALINA_HOME/bin/catalina.sh,在 “OS specific support …” 段之前添加(或追加到已有的 JAVA_OPTS),位置很关键,避免被后续脚本覆盖:
- 示例(JDK 8+,含元空间与栈):
JAVA_OPTS="$JAVA_OPTS \ -server \ -Xms2g -Xmx2g \ -Xss256k \ -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \ -Djava.awt.headless=true" - 如为 JDK 7:将 -XX:MetaspaceSize/MaxMetaspaceSize 替换为 -XX:PermSize=… -XX:MaxPermSize=…。
- 示例(JDK 8+,含元空间与栈):
- 作为服务运行时(如通过 systemd 管理的 tomcat 服务),需把上述参数写入服务的 Environment=JAVA_OPTS=… 配置中,或在 /usr/share/tomcat9/bin/setenv.sh(若不存在可创建)中导出,确保服务启动脚本能读取到。
- 重启并验证:sudo systemctl restart tomcat9,再用 jmap -heap 与 jstat -gcutil 确认参数生效与 GC 状况。
四、应用侧优化与常见陷阱
- 排查内存泄漏与对象膨胀:结合 jmap/jstack 与 VisualVM/JConsole 做堆转储与热点分析,清理静态集合、缓存滥用、未关闭资源(如 InputStream/Connection)、大对象生命周期过长等问题。
- 控制类加载与热部署频率:避免频繁 redeploy 导致 PermGen/Metaspace 持续增长;共享 JAR、减少 Web 应用私有副本。
- 连接与线程治理:合理设置 maxThreads/acceptCount,并配合 Nginx/HAProxy 做连接限流与超时,防止雪崩与线程耗尽。
五、常用参数与监控命令速查
- 常用 JVM 参数
- 堆与栈:-Xms/-Xmx(建议等值)、-Xss(线程栈,如 256k)
- 元空间(JDK 8+):-XX:MetaspaceSize=… -XX:MaxMetaspaceSize=…
- 永久代(JDK 7-):-XX:PermSize=… -XX:MaxPermSize=…
- 模式与特性:-server、-Djava.awt.headless=true
- 常用监控命令
- 进程:ps -ef | grep java
- 堆与 GC:jmap -heap 、jstat -gcutil 1000 30
- 线程与栈:top -H -p ;printf “%x\n” ;jstack | grep -A 30
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 如何解决Ubuntu Tomcat内存溢出问题
本文地址: https://pptw.com/jishu/787458.html
