必须使用setenv.sh或setenv.bat管理CATALINA_OPTS,因其优先级高于系统环境变量、避免多实例冲突、防止升级覆盖,且仅对当前Tomcat实例生效;Linux需chmod +x,Windows用set语法,参数须适配JDK版本并经jcmd或管理页验证。

CATALINA_OPTS 不是可有可无的启动参数容器,而是 Tomcat 启动时 JVM 实际生效的唯一内存与调试配置入口。直接改 catalina.bat 或 catalina.sh 里的 JAVA_OPTS 是过时机做法,且容易被覆盖;用系统级环境变量又会导致多实例冲突——正确路径只有一条:靠 setenv.sh(Linux/macOS)或 setenv.bat(Windows)。
为什么必须用 setenv.sh / setenv.bat 而不是全局环境变量
全局设置 CATALINA_OPTS 会污染所有 Tomcat 实例,尤其当你本地同时跑 Tomcat 9(需 JDK 11)和 Tomcat 10+(需 JDK 17)时,CATALINA_OPTS 里混着不同 JVM 参数,一启动就报 Unrecognized VM option 或直接静默失败。而 setenv.* 文件在每个 Tomcat 的 bin/ 目录下独立存在,优先级高于系统环境变量,且只对当前实例生效。
- Tomcat 启动脚本(
startup.sh/startup.bat)会在最开始 source 或 callsetenv.*,如果该文件存在 - 若不存在,它才 fallback 到读取系统环境变量
CATALINA_OPTS - 你手动在终端执行
export CATALINA_OPTS=...只对当前 shell 有效,无法用于服务化部署(如 systemd、Windows Service)
setenv.sh 中 CATALINA_OPTS 的典型写法(含 Java 8+ 兼容)
Java 8 起永久代(PermGen)被元空间(Metaspace)取代,-XX:MaxPermSize 已失效,硬写会触发 JVM 启动警告甚至拒绝启动。以下写法适配 Java 8–21:
#!/bin/sh export CATALINA_OPTS="-Xms2G -Xmx2G -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M -Xss256k"
-
-Xms和-Xmx建议设为相同值,避免运行时堆扩容带来 GC 暂停抖动 -
-XX:MetaspaceSize设得太低(如默认 128M)会导致频繁元空间 GC;设太高(如 1G)又浪费,256M 是多数 Web 应用安全起点 -
-Xss256k是线程栈大小,调小可支撑更多并发线程,但低于 128k 可能触发StackOverflowError(尤其用大量递归或深度 AOP) - 不要在
CATALINA_OPTS里写-Dfile.encoding=UTF-8这类系统属性——它们应放在JAVA_TOOL_OPTIONS或应用代码里,否则某些 JVM 版本会忽略
远程调试必须加的参数组合(address 必须显式指定)
只写 -Xdebug -Xrunjdwp 在新版本 JDK(11+)上大概率失败,因为默认 transport 是 dt_shmem(仅 Windows 有效),而 IDE(IntelliJ/Eclipse)默认连 dt_socket。正确写法:
export CATALINA_OPTS="-Xms2G -Xmx2G -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"
-
address=*:8000表示监听所有网卡(包括 Docker 容器内访问),不是localhost:8000(后者容器外连不上) -
suspend=n是必须的,设成y会让 Tomcat 卡在启动阶段等 IDE 连接,超时后自动退出 -
-agentlib:jdwp=...替代了老旧的-Xrunjdwp,JDK 9+ 已弃用后者 - Windows 下若用
setenv.bat,语法为:set CATALINA_OPTS=-Xms2G -Xmx2G -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000
验证 CATALINA_OPTS 是否真正生效的唯一可靠方式
别信 echo $CATALINA_OPTS 或看日志里有没有 “Starting JVM with...” —— 那些只是打印字符串,不代表 JVM 实际加载了这些参数。真正验证方法只有两个:
- 启动后进 Tomcat 管理页(
http://localhost:8080/manager/status),点“Server Status”,在 JVM 属性区块找java.vm.name和sun.boot.library.path下方的jvm.memory和jvm.arguments,这里显示的是 JVM 实际解析后的完整参数列表 - 用
jps -l找到 Tomcat 进程 PID,再执行jcmd <pid> VM.flags(JDK 7+)或jinfo -flags <pid>,输出中必须包含你写的全部-Xms、-XX:MetaspaceSize等项 - 如果
jcmd报错 “Not able to attach to process”,说明进程启用了-XX:+DisableAttachMechanism(常见于生产加固),此时只能靠第一种方式
最容易被忽略的是:setenv.sh 文件权限必须是可执行(chmod +x bin/setenv.sh),否则 Linux/macOS 下 Tomcat 启动脚本会静默跳过它,连错误提示都没有。

















