生产环境Java部署必须严格校验JDK版本兼容性、Tomcat类加载顺序、JVM参数配置及安全端口管理。需确保java/javac版本一致,Spring Boot 3.x要求JDK 17,log4j-core等依赖需同步升级;Tomcat中jar应按层级规范放置,避免WEB-INF/lib冲突;JVM堆内存须显式设定,禁用默认端口与明文管理界面,并彻底清理残留旧版jar和错误JAVA_HOME路径。

Java生产环境必须确认JDK版本与应用兼容性
很多线上问题根源是JDK版本错配——比如用JDK 17编译的record类,在JDK 8上直接抛java.lang.UnsupportedClassVersionError。生产环境不能只看“有JDK”,而要看java -version输出是否匹配构建时的source和target参数。
- Spring Boot 3.x 要求最低 JDK 17,老项目升级前必须验证所有依赖(如
log4j-core2.17+才完全支持JDK 17) - 使用
javac -version和java -version分别检查编译器与运行时版本,二者不一致极易埋雷 - 推荐在
/opt/java下并行安装多个JDK,并通过update-alternatives --config java切换,避免全局污染
Tomcat部署WAR包时CLASSPATH加载顺序很关键
Tomcat的类加载机制不是简单“把jar丢进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里重复打包,便于连接池统一管理 - 若需隔离日志实现(如Logback),确保
WEB-INF/lib中只有logback-classic.jar和logback-core.jar,删掉冲突的slf4j-log4j12.jar
启动脚本必须显式指定JVM参数而非依赖默认值
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应用未设密码——这等于把服务器大门敞开。
立即学习“Java免费学习笔记(深入)”;
- 修改
$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路径——这些细节不会报错,但会让问题在凌晨三点突然爆发。










