




生产环境Java部署必须严格校验JDK版本兼容性、Tomcat类加载顺序、JVM参数配置及安全端口管理。需确保java/javac版本一致,Spring Boot 3.x要求JDK 17,log4j-core等依赖需同步升级;Tomcat中jar应按层级规范放置,避免WEB-INF/lib冲突;JVM堆内存须显式设定,禁用默认端口与明文管理界面,并彻底清理残留旧版jar和错误JAVA_HOME路径。
很多线上问题根源是JDK版本错配——比如用JDK 17编译的record类,在JDK 8上直接抛java.lang.UnsupportedClassVersionError。生产环境不能只看“有JDK”,而要看java -version输出是否匹配构建时的source和target参数。
log4j-core 2.17+才完全支持JDK 17)javac -version和java -version分别检查编译器与运行时版本,二者不一致极易埋雷/opt/java下并行安装多个JDK,并通过update-alternatives --config java切换,避免全局污染Tomcat的类加

lib就行”。它按Bootstrap → System → Common → Catalina → Shared → Webapp层级加载,WEB-INF/lib下的jar优先级最高——这意味着你放进去的slf4j-simple.jar会覆盖$CATALINA_HOME/lib里的slf4j-api.jar,导致NoClassDefFoundError。
WEB-INF/lib中打包javax.servlet-api或tomcat-jdbc等容器已提供的API$CATALINA_HOME/lib,而非每个WAR里重复打包,便于连接池统一管理WEB-INF/lib中只有logback-classic.jar和logback-core.jar,删掉冲突的slf4j-log4j12.jar
Linux服务默认以root用户启动,但JVM堆内存不设上限时,-Xms和-Xmx会取物理内存的1/4,一台64G机器可能直接分配16G——这会挤占系统缓存、触发频繁GC甚至OOM Killer杀进程。
$CATALINA_HOME/bin/setenv.sh中写死参数:export JAVA_OPTS="-Xms2g -Xmx2g -XX:+UseG1GC -Dfile.encoding=UTF-8"
-Duser.timezone=GMT+8,否则new Date()在日志或定时任务中可能跨天错乱-server(JDK 8u212+已废弃),改用-XX:+AlwaysPreTouch提前触碰内存页,减少首次请求延迟刚解压的Tomcat默认开放8005(shutdown端口)、8080(HTTP)、8009(AJP),且manager应用未设密码——这等于把服务器大门敞开。
$CATALINA_HOME/conf/server.xml:将port="8005"改为非标准端口(如8015),并在shutdown属性加随机字符串conf/tomcat-users.xml中默认的admin角色,新增带manager-gui权限的独立用户,并用digest.bat/sh加密密码webapps/manager和webapps/host-manager目录,比“改密码”更彻底真正麻烦的从来不是装不上,而是某个log4j-core-2.14.1.jar藏在某个子模块的lib目录里没被清理干净,或者JAVA_HOME指向了/usr/bin/java这个符号链接而非真实JDK路径——这些细节不会报错,但会让问题在凌晨三点突然爆发。