Linux Tomcat如何解决内存溢出
导读:Linux Tomcat 内存溢出定位与解决 一、先快速判断错误类型 查看 $CATALINA_HOME/logs/catalina.out,根据异常关键字确定方向: Java heap space:堆内存不足,对象申请超过 -Xmx...
Linux Tomcat 内存溢出定位与解决
一、先快速判断错误类型
- 查看 $CATALINA_HOME/logs/catalina.out,根据异常关键字确定方向:
- Java heap space:堆内存不足,对象申请超过 -Xmx 或存在内存泄漏。
- PermGen space:JDK 7 及更早的永久代不足(常见于大量类/JSP 预编译、重复 jar)。
- Metaspace:JDK 8+ 的类元数据区不足(对应 -XX:MaxMetaspaceSize)。
- unable to create new native thread:系统资源/容器限制导致无法创建更多线程(如 ulimit -u、容器配额)。
- 示例命令:
tail -100 $CATALINA_HOME/logs/catalina.out | grep -i "OutOfMemoryError\|java.lang.OutOfMemoryError"。
二、对应场景与解决方案
- 堆内存不足(Java heap space)
- 适度增大堆:设置 -Xms 与 -Xmx(建议等值,如 -Xms2g -Xmx2g),并控制总堆不超过物理内存的约80%;可按需配置新生代 -Xmn≈-Xmx 的 1/4。
- 打开 GC 日志,观察是否频繁 Full GC 且回收效果差:
-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps。 - 发生 OOM 时获取堆转储:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/heap.hprof,用 Eclipse MAT/jvisualvm 分析泄漏对象与引用链。
- 类元数据区不足(PermGen/Metaspace)
- JDK 7 及更早:增大永久代(示例:
-XX:PermSize=256m -XX:MaxPermSize=512m)。 - JDK 8+:改用元空间(示例:
-XX:MaxMetaspaceSize=512m;不设上限时受容器/系统内存约束)。 - 减少重复 jar、避免应用间 jar 冲突,必要时将公共依赖放入 $CATALINA_HOME/shared/lib(视版本与类加载器而定)。
- JDK 7 及更早:增大永久代(示例:
- 线程创建失败(unable to create new native thread)
- 检查系统/容器限制:
ulimit -u(用户进程数)、ulimit -n(文件句柄);必要时调大并同步调整 Tomcat 的 maxThreads(在 conf/server.xml 的 Executor/Connector 中)。 - 排查线程泄漏(线程数随时间持续增长):用 jstack 采样线程栈,定位创建线程的代码路径并修复。
- 检查系统/容器限制:
- 运行一段时间变慢或 OOM 反复
- 检查日志滚动与磁盘占用,避免 catalina.out 无限增长(可用 cronolog 按时间切割)。
- 排查业务侧问题:大对象/大文件一次性加载进内存、集合/缓存未及时清理、定时任务叠加等。
三、Linux 下正确修改 Tomcat 的 JVM 参数
- 解压版或前台启动:编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 之前添加(示例为 JDK 8+):
export JAVA_OPTS="$JAVA_OPTS -server \ -Xms2g -Xmx2g \ -Xmn512m \ -XX:MaxMetaspaceSize=512m \ -verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps \ -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/heap.hprof"- 注意:JDK 8+ 不要再用 -XX:PermSize/MaxPermSize(已被移除)。
- systemd 服务方式:在 /etc/systemd/system/tomcat.service 的 [Service] 段使用 Environment 或 ExecStart 前置参数,例如:
修改后执行:Environment="JAVA_OPTS=-server -Xms2g -Xmx2g -Xmn512m -XX:MaxMetaspaceSize=512m" ExecStart=/opt/tomcat/bin/startup.shsystemctl daemon-reload & & systemctl restart tomcat。 - 验证是否生效:
ps -ef | grep tomcat | grep -E "Xms|Xmx|MaxMetaspaceSize";或在 /manager/status(需配置用户)查看 Free/Total/Max memory。
四、参数建议与常见坑
- 建议基线(按机器内存与负载调整):
- 堆:
-Xms与-Xmx等值,通常设为可用内存的50%–60%,不超过约80%;新生代-Xmn≈-Xmx/4。 - 元空间:
-XX:MaxMetaspaceSize=…(如 512m/1g),避免无限制增长。 - GC 日志与 OOM Dump:便于定位与复盘,生产建议长期开启(注意磁盘与性能影响)。
- 堆:
- 常见坑
- 在 catalina.sh 中错误使用
JAVA_OPTS="$JAVA_OPTS …"前未导出,或被其他脚本覆盖;建议统一在脚本前部export且避免重复拼接。 - 将 -Xms/-Xmx 设得过大导致系统内存紧张、换页/GC 压力过大;或过小引发频繁 Full GC。
- 误把 PermSize/MaxPermSize 用于 JDK 8+;JDK 8+ 应使用 Metaspace 相关参数。
- 在 catalina.sh 中错误使用
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Linux Tomcat如何解决内存溢出
本文地址: https://pptw.com/jishu/767217.html
