How to Safely Optimize Tomcat Memory for Stable Production
This guide walks you through why Tomcat's default JVM settings are insufficient, common pitfalls when manually editing catalina.sh, and the recommended, maintainable approach using setenv.sh to configure heap, Metaspace, and GC options for reliable, high‑performance server operation.
Ever done this? Open tomcat/bin/catalina.sh , paste JAVA_OPTS=... at the end, restart Tomcat, and think everything is fine… Result: memory changes not applied, startup errors, PermGen space issues, or lost configuration after an upgrade.
Tomcat’s default JVM parameters are very conservative: the heap may be only 64‑128 MB, PermGen is tiny, and a moderately complex web app (especially Spring, Hibernate, MyBatis) can trigger OutOfMemoryError within minutes.
堆内存可能只有 64~128MB
永久代(PermGen)小得可怜
一旦部署稍复杂的 Web 应用(尤其是 Spring、Hibernate、MyBatis),
几分钟内就可能触发 OutOfMemoryError!Proper tuning yields faster startup, >80 % reduction in GC cycles, and significantly improved system stability.
启动更快
GC 次数减少 80%+
系统稳定性大幅提升Common Wrong Practices (Which ones have you done?)
错误做法
后果
在 catalina.sh 末尾加 JAVA_OPTS 可能被脚本后续逻辑覆盖,不生效!
直接修改 cygwin=false 之后的位置
部分版本 Tomcat 会重置变量,配置丢失
JDK 8+ 仍使用 -XX:MaxPermSize 参数被忽略,Metaspace 无限增长 → 内存爆掉 -Xms 与 -Xmx 设得不一样
JVM 动态扩容引发 Full GC,性能抖动
📌 真相:Tomcat 官方根本不推荐直接改 catalina.sh !
Correct Approach: Use setenv.sh (Official Recommendation)
Step 1: Create the configuration file
# 进入 Tomcat 的 bin 目录
cd /your/tomcat/bin
# 创建 setenv.sh(注意:不是 catalina.sh!)
cat > setenv.sh <<'EOF'
#!/bin/bash
# Tomcat JVM 内存优化配置
# —— 专为生产环境设计
# JDK 8 及以上(推荐)
JAVA_OPTS="-server \
-Xms1024m \
-Xmx1024m \
-XX:MetaspaceSize=256M \
-XX:MaxMetaspaceSize=512M \
-XX:+UseG1GC \
-XX:+DisableExplicitGC"
# JDK 7 及以下(已不推荐)
# JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=512m"
EOFStep 2: Add execution permission
chmod +x setenv.shStep 3: Restart Tomcat
./shutdown.sh
./startup.shWhy This Is Safer
catalina.sh 在启动时会自动加载 setenv.sh(官方机制)
升级 Tomcat 时,无需重新修改核心脚本
配置集中、清晰、可版本管理How to Verify the Memory Configuration Took Effect
Method 1: Check startup logs
grep "JAVA_OPTS" logs/catalina.out
✅ 正确输出:
JAVA_OPTS: "-server -Xms1024m -Xmx1024m -XX:MetaspaceSize=256M ..."Method 2: Use jps + jinfo
# Find Tomcat PID
jps | grep Bootstrap
# Assuming PID=12345, view actual JVM flags
jinfo -flags 12345 | grep -E "Xmx|Metaspace"Parameter Details (Recommended per Scenario)
场景
推荐配置
开发/测试环境
-Xms512m -Xmx512m -XX:MetaspaceSize=128M
中小型生产系统
-Xms1024m -Xmx1024m -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M
高并发/大应用
-Xms4096m -Xmx4096m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
Golden Rules
-Xms = -Xmx(避免堆动态伸缩)
JDK 8+ 必须用 Metaspace,别再写 PermSize!
生产环境建议启用 G1GC(低延迟)Additional Suggestions: Make Tuning Smarter
配合监控
使用 Prometheus + JMX Exporter,实时观察堆内存、Metaspace 使用率。
设置 OOM 自动 dump
在 JAVA_OPTS 中加入:
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/data/logs/tomcat-oom.hprofDo not blindly increase heap size; a single Tomcat instance should not exceed 8 GB heap, otherwise GC pauses become too long.
Final Note
Optimization is not “the bigger, the better”, but “just right”.
A proper setenv.sh beats ten blind restarts.
From today, stop randomly editing catalina.sh and adopt the official, reliable method.
Xiao Liu Lab
An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
