如何解决Linux Tomcat内存溢出问题
导读:Linux Tomcat 内存溢出定位与解决 一、先快速定位错误类型 查看 $CATALINA_HOME/logs/catalina.out,根据异常关键词判断是哪块内存出问题: Java heap space:堆内存不足,常见于对象创...
Linux Tomcat 内存溢出定位与解决
一、先快速定位错误类型
- 查看 $CATALINA_HOME/logs/catalina.out,根据异常关键词判断是哪块内存出问题:
- Java heap space:堆内存不足,常见于对象创建过多且未及时释放、一次性加载大数据等。
- PermGen space(JDK 7 及更早):永久代/方法区不足,常见于应用或 JSP 预编译加载大量类、重复加载第三方 JAR。
- Metaspace(JDK 8+):元空间不足,类元数据过多或类加载器泄漏。
- unable to create new native thread:系统或容器对线程/内存资源限制导致无法创建新线程。以上关键词通常直接出现在日志中,可据此选择对应处理路径。
二、对应场景与解决方案
- 堆内存不足 Java heap space
- 调整堆大小:在 bin/catalina.sh 的 cygwin=false 之前设置(示例为 4GB,可按机器内存调整):
- JAVA_OPTS=“-server -Xms4g -Xmx4g -Xmn1g”
- 建议将 -Xms 与 -Xmx 设为相同,避免运行期频繁扩缩堆;-Xmn 通常设为 -Xmx 的 1/4 左右,其余留给老年代。
- 打开 GC 日志,便于观察回收效果:
- JAVA_OPTS=“$JAVA_OPTS -verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps”
- 若仍 OOM,抓取堆转储分析泄漏对象:
- JAVA_OPTS=“$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/”
- 调整堆大小:在 bin/catalina.sh 的 cygwin=false 之前设置(示例为 4GB,可按机器内存调整):
- 永久代或元空间不足
- JDK 7 及更早(PermGen):
- JAVA_OPTS=“$JAVA_OPTS -XX:PermSize=256m -XX:MaxPermSize=512m”
- JDK 8+(Metaspace,默认无上限,建议设上限并观察):
- JAVA_OPTS=“$JAVA_OPTS -XX:MaxMetaspaceSize=512m”
- 减少类加载重复:将公共的第三方 JAR 放到 $CATALINA_HOME/shared/lib(适用于多应用共享,减少重复占用)。
- JDK 7 及更早(PermGen):
- 线程或系统资源限制导致 unable to create new native thread
- 检查系统限制:ulimit -u(用户最大进程/线程数)、ulimit -v(虚拟内存)、ulimit -n(打开文件数)。
- 适当增大限制(需 root 或系统管理员),并优化应用线程模型(控制线程池队列与拒绝策略,避免无界队列)。
- 运行一段时间变慢或 OOM
- 检查日志滚动:对 catalina.out 按时间切割(如使用 Cronolog),避免单文件过大引发 I/O 与内存压力。
三、配置位置与生效方式
- 解压版 Tomcat(Linux)
- 编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 之前添加 JAVA_OPTS(如上示例),保存后执行:
- ./shutdown.sh & & ./startup.sh
- 编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 之前添加 JAVA_OPTS(如上示例),保存后执行:
- 安装为系统服务(systemd)
- 不建议在脚本里用 JAVA_OPTS,优先在 systemd 服务单元中配置:
- 编辑 /etc/systemd/system/tomcat.service,在 [Service] 段加入:
- Environment=“JAVA_OPTS=-server -Xms4g -Xmx4g -Xmn1g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tomcat/logs/”
- 执行:systemctl daemon-reload & & systemctl restart tomcat
- 编辑 /etc/systemd/system/tomcat.service,在 [Service] 段加入:
- 不建议在脚本里用 JAVA_OPTS,优先在 systemd 服务单元中配置:
- 验证是否生效
- 查看进程参数:ps -ef | grep tomcat | grep -E ‘Xms|Xmx|MaxMetaspaceSize|MaxPermSize’
- 观察 GC 日志与(如有)堆转储文件是否生成于 $CATALINA_HOME/logs/。
四、监控与根因排查
- 实时监控
- 本地/远程使用 jvisualvm、jconsole 观察堆、类、线程、CPU 等指标;必要时通过 JMX 远程连接 Tomcat 实例。
- 堆转储分析
- 发生 OOM 后,用 Eclipse MAT 或 VisualVM 打开 .hprof 文件,按“支配树/GC Roots 最短路径”定位占用最多且无法回收的对象,回溯到创建位置与引用链,修复代码或缓存策略。
- 常见代码与架构问题
- 一次性读取/处理海量数据(如 > 10 万条)导致瞬时堆暴涨:改为分页/流式处理。
- 集合、缓存、会话中对象长期持有引用未清理:及时清理或设置失效策略。
- 死循环/递归或线程执行时间过长:优化算法、拆分任务、限流与超时控制。
五、安全调参与容量规划建议
- 堆上限不要超过可用物理内存的 70%~80%,为操作系统与其他进程预留空间;-Xms 与 -Xmx 设为相同可减少停顿;-Xmn≈-Xmx/4 作为起点,再结合 GC 日志与业务对象生命周期微调。
- 生产环境谨慎频繁 HeapDump(会“冻结”应用),只在问题复现窗口开启,并配置合适的 MaxMetaspaceSize/MaxPermSize 上限,避免无界增长。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 如何解决Linux Tomcat内存溢出问题
本文地址: https://pptw.com/jishu/760138.html
