汇知百科
白蓝主题五 · 清爽阅读
首页  > 故障排查

Tomcat堆内存配置踩坑实录:启动慢、频繁GC、直接OOM?

公司新上线一个后台管理服务,部署到测试环境的Tomcat后,页面响应越来越慢,后台日志里隔三差五就冒出java.lang.OutOfMemoryError: Java heap space。重启Tomcat能撑一两个小时,接着又卡死——这哪是业务问题,分明是内存没配对。

为啥堆内存总出事?

Tomcat本身是个Java进程,所有Web应用(比如你的Spring Boot打包成war丢进去)都跑在它的JVM里。堆内存就是JVM里专门存对象的地方。配小了,对象一多就溢出;配太大,GC停顿时间拉长,请求卡在那儿不动;更麻烦的是,32位系统或某些老版本JDK还有堆上限限制,硬塞4G可能根本起不来。

去哪改?认准catalina.sh或catalina.bat

Linux下进$CATALINA_HOME/bin/,打开catalina.sh;Windows就找catalina.bat。别去改setenv.sh(万一不存在还得自己建),也别碰server.xml——那玩意儿管不了JVM参数。

找到类似这样的行(通常在注释块下面):

# OS specific support.  $var _must_ be set to either true or false.

在这附近加一行(注意位置:必须在exec "$PRGDIR"/"$_RUNJAVA"之前,否则不生效):

export JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC"

Windows对应写法:

set JAVA_OPTS=-Xms512m -Xmx2g -XX:+UseG1GC

参数咋选?记住三个数

-Xms:JVM启动时直接分配的堆大小,建议和-Xmx设成一样,避免运行中动态扩容导致STW暂停;
-Xmx:堆最大值,别超物理内存的75%,比如服务器有8G内存,Tomcat独占的话,-Xmx设到4g比较稳妥;
-XX:+UseG1GC:JDK8u20以后推荐用G1垃圾回收器,大堆下比Parallel更可控。

别瞎抄网上“-Xmx4g”——你服务器总共才4G内存?留点给操作系统、其他进程和Metaspace,不然Swap狂刷,比OOM还难查。

验证有没有生效?

启动Tomcat后,执行:
ps -ef | grep tomcat(Linux)或任务管理器看Java进程命令行参数。
看到类似-Xms512m -Xmx2g就对了。再进Tomcat管理页(http://localhost:8080/manager/status),右上角「JVM信息」里也能看到当前堆已用/最大值。

配完还是OOM?试试加个监控开关

在JAVA_OPTS里补上这两句,下次OOM时会自动生成堆转储文件(heap dump),方便用VisualVM或JProfiler分析:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tomcat/logs/heap.hprof

路径记得提前创建好目录并赋权,不然dump写不进去,日志里连错都不报,纯静默失败。

有次线上遇到一个定时任务每小时扫10万条订单,开发说“逻辑很简单”,结果一跑就OOM。抓了heap dump一看,List里塞了几万个未关闭的数据库连接对象——堆内存配再大也没用,得修代码。所以配参数只是第一步,它暴露问题,但不代替排查。