CentOS8为Tomcat10设置JVM内存参数:手把手调优,拒绝卡顿与OOM
CentOS8为Tomcat10设置JVM内存参数:手把手调优,拒绝卡顿与OOM

线上业务刚上线,页面转圈半天没反应,日志里漂着一行OutOfMemoryError: GC overhead limit exceeded,老板在群里疯狂艾特你。别慌,九成是JVM内存没给够,或者给得不对。CentOS8+Tomcat10这套组合,默认启动参数温柔得像小猫,访问量一上来就趴窝。今天把压箱底的步骤掏出来,照着敲,十分钟让服务重新生龙活虎。
Tomcat10在CentOS8里怎么启动
很多人装完Tomcat10直接systemctl start tomcat就不管了,其实Systemd调的是/usr/share/tomcat/bin/startup.sh,真正管内存的是catalina.sh里的JAVA_OPTS。找不到变量就按默认走,初始堆才百兆,不崩才怪。想永久生效,别去改catalina.sh本身,升级会被覆盖;正确姿势是新建一个Systemd覆盖单元,把内存参数写进去,干净又安全。
第一步:用root看一眼当前内存上限
ps -ef | grep tomcat把进程号揪出来,接着jmap -heap PID,一眼能看到MaxHeapSize只有268435456(256M)。先别急着加,先算老机器还剩多少空闲:free -h看available列,给系统留1G,剩下的才能分给JVM。记住,堆+元空间+直接内存+线程栈都得算进去,别只盯-Xmx。
第二步:创建Systemd覆盖单元

CentOS8用systemctl edit tomcat打开临时编辑窗,写入:
[Service]Environment='JAVA_OPTS=-Xms1g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Djava.awt.headless=true'
保存后systemctl daemon-reload,再systemctl restart tomcat。这条命令里,-Xms1g让堆一开始就拿到1G,避免运行时频繁申请;-Xmx2g是上限,给业务留增长空间;MetaspaceSize把类元数据区锁在512M,防止动态类加载把本机内存打爆。
第三步:验证有没有生效

重启后立刻jmap -heap PID,看到MaxHeapSize = 2147483648(2G)才算数。再用jstat -gc PID 5s跑十行,观察EU与OU列,如果EU飙高后迅速回落,说明G1GC的预测停顿在起作用,用户请求不会被长时间挂起。
第四步:把线程栈也顺手收紧
高并发场景下,一个请求一个线程,默认每条线程栈1M,一千条就吃掉1G。把-Xss512k追加到JAVA_OPTS,直接省出一半内存,CentOS8内核不会报警,Tomcat10照样稳。改完记得压测,ab -c 1000 -n 50000跑一轮,看是否出现StackOverflowError,没有就放心上线。
第五步:防踩坑锦囊
1. 禁止写swap:swapoff -a再注释掉/etc/fstab里的swap行,JVM一换到磁盘,GC停顿立刻从毫秒级飙到秒级。
关闭透明大页:echo never > /sys/kernel/mm/transparent_hugepage/enabled,这东西会让G1GC的内存整理动作放大十倍。
文件句柄数:在/etc/security/limits.conf里给tomcat用户加到65535,避免高并发时Too many open files。
别混用JAVAOPTS与CATALINAOPTS:前者管启动、关闭脚本,后者只影响运行时;Systemd场景下统一写JAVA_OPTS最省心。
第六步:让配置随机器重启自动生效
CentOS8重启后,Systemd会重新读/etc/systemd/system/tomcat.service.d/override.conf,内存参数不会丢。为了双保险,把JAVA_OPTS再写一份到/etc/tomcat/tomcat.conf,这是部分发行版提供的兜底文件,两边同时存在时,Systemd优先级更高,互不冲突。
第七步:监控告警别忘了
配完参数只是起点,上线后把jstat -gc的日志丢进ELK,或者装个prometheus-jmx-exporter,把jvmmemoryusedbytes、jvmgccollectionseconds_sum两个指标拉到Grafana,超过80%就短信。别等老年代飙到99%才想起加机器,那时候已经来不及了。
照着以上七步走,CentOS8上的Tomcat10内存就算稳了。再出现OutOfMemoryError,别急着甩锅给代码,先回头对照配置,十有八九是参数漏了哪一步。服务器资源永远有限,把每一兆内存都花在刀刃上,才是运维人真正的KPI。

