CentOS下Tomcat内存调优实操指南

一配置入口与原则

推荐在$CATALINA_HOME/bin/setenv.sh中设置环境变量(文件不存在则新建),避免在catalina.sh内直接修改;如使用系统服务包,也可在/etc/sysconfig/tomcat或/etc/default/tomcat中设置JAVA_OPTS。设置完成后执行:

sudosystemctlrestarttomcat
。原则是:将-Xms与-Xmx设为相同以避免运行期扩缩堆带来的停顿;堆大小一般不超过物理内存的50%~80%,并预留内存给元空间Metaspace、本地内存(DirectMemory/NIO)、操作系统与PageCache。

二关键JVM参数与版本差异

常用参数说明

堆与栈:-Xms/-Xmx(初始/最大堆,建议等值)、-Xss(线程栈,默认约512KB,过高会减少可创建线程数,过低易栈溢出)。

元空间(JDK8+):-XX:MetaspaceSize=…-XX:MaxMetaspaceSize=…(替代已废弃的PermGen)。

GC选择:大堆(如≥6GB)且关注停顿时间时优先-XX:+UseG1GC,可配合-XX:MaxGCPauseMillis=…设定目标暂停时间;吞吐优先可考虑并行GC。

故障排查:开启-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/log/便于分析OOM。

版本差异与示例

JDK7及以下(PermGen):

示例:

JAVA_OPTS="-Xms2g-Xmx2g-XX:PermSize=256m-XX:MaxPermSize=512m-XX:+UseG1GC"

JDK8+(Metaspace):

示例:

JAVA_OPTS="-Xms4g-Xmx4g-XX:MetaspaceSize=256m-XX:MaxMetaspaceSize=512m-XX:+UseG1GC-XX:MaxGCPauseMillis=500-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/log/"

三监控与诊断

实时观察GC与内存:

jstat-gcutil1000
(每1s输出一次),关注YGC/YGCT、FGC/FGCT、GCT等指标变化。

堆转储与分析:发生OOM或手动触发时执行

jmap-dump:live,format=b,file=heap.hprof
,再用jhat或VisualVM/MAT分析对象分布与泄漏根因。

线上建议接入Prometheus+Grafana等监控告警,持续跟踪堆、GC、线程与类加载等指标。

四常见场景与建议配置

小内存实例(如2GB内存):

JAVA_OPTS="-Xms1g-Xmx1g-XX:MetaspaceSize=128m-XX:MaxMetaspaceSize=256m-XX:+UseG1GC-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/log/"

中等内存实例(如8GB内存):

JAVA_OPTS="-Xms6g-Xmx6g-XX:MetaspaceSize=256m-XX:MaxMetaspaceSize=512m-XX:+UseG1GC-XX:MaxGCPauseMillis=500-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/log/"

大内存与低停顿(如16GB内存):

JAVA_OPTS="-Xms12g-Xmx12g-XX:MetaspaceSize=256m-XX:MaxMetaspaceSize=512m-XX:+UseG1GC-XX:MaxGCPauseMillis=200-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/data/log/-XX:G1ReservePercent=15"
(可按应用对象生命周期适当调节G1ReservePercent)。

说明:堆上限通常取物理内存的1/2~3/4并留足余量;若应用大量使用NIO/DirectBuffer,需额外预留本地内存;线程栈-Xss常用512KB~1MB,过高会限制并发线程数,过低可能StackOverflowError。

五易错点与排查路径

将-Xms与-Xmx设为不同值会引发运行期堆扩缩导致停顿;堆过大导致单次FullGC时间过长;-Xss过大/过小都会影响并发与稳定性。

在JDK8+仍配置PermSize/MaxPermSize不会生效;应改用Metaspace参数。

仅修改catalina.sh而未使用setenv.sh或服务环境变量,可能导致变更不生效或被包管理脚本覆盖。

出现OutOfMemoryError:Javaheapspace时,先开启并分析堆转储;若是Metaspace或DirectMemory,需分别调整MetaspaceSize/MaxMetaspaceSize与NIO/缓存策略。