答案是完全可以,只要把两个JDK放进不同的安装目录,再通过配置JAVA_HOME和PATH来切换,它们就能在同一个系统里各用各的,互不干扰。
我自己的开发机上就常年挂着JDK 8和JDK 17,一个用来跑老项目,一个用来试新框架,切换起来也就一条命令的事,这套逻辑搬到服务器上完全一样,只是你要多留神环境变量的优先级,别让系统替你“乱点鸳鸯谱”。
一个服务器装两个jdk有什么用
有同事第一次听说服务器上装两个JDK,第一反应是“这也太折腾了”,等你真遇到下面这些场景,就知道它多实用了。
- 老项目还跑在JDK 8上,新服务又要求JDK 17起步,改代码一时半会儿完不成,版本又不敢降,只能先共存
- 运维接手历史机器,发现上面已经装了一套JDK,新部署的脚本又绑定另一个版本,卸载旧的会出事
- 同一台服务器上,Tomcat里跑着JDK 8的旧应用,旁边又开了个新版Spring Boot服务,强行要求JDK 17
核心原则一句话:JDK的安装目录互相独立,哪个版本生效由JAVA_HOME和PATH的顺序说了算,而不是由你“装了几下”决定的。
近年来企业服务器上凡是需要多版本共存的,基本走这条路线,比反复卸载重装省心多了。
Linux服务器怎么装两个jdk版本
我拿CentOS 7.x举例,其他发行版把包管理器换一下就通用了。
第一步:找两个干净的tar.gz解压包
不要用yum装系统自带的openjdk,它的目录结构乱,而且跟系统绑定太紧。推荐下载官方tar.gz解压包,放到/usr/local/jdk目录下,一个版本一个文件夹。
mkdir -p /usr/local/jdk cd /usr/local/jdk tar -zxvf jdk-8u202-linux-x64.tar.gz tar -zxvf jdk-17_linux_x64_bin.tar.gz
解压完的目录结构类似:
/usr/local/jdk/
├── jdk1.8.0_202
└── jdk-17.0.2
第二步:维护两个环境变量文件
直接在/etc/profile里改来改去,切一次版本改一次文件,迟早改晕,更干净的玩法是创建两个独立的profile文件,分别对应两个JDK。
创建JDK 8的环境变量文件:
vim /etc/profile.d/jdk8.sh
写入:
export JAVA_HOME=/usr/local/jdk/jdk1.8.0_202 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
创建JDK 17的环境变量文件:
vim /etc/profile.d/jdk17.sh
写入:
export JAVA_HOME=/usr/local/jdk/jdk-17.0.2 export PATH=$JAVA_HOME/bin:$PATH
两个文件里的路径一定不能写反,写反了等于白干。
当下需要哪个版本,就source对应的文件:
source /etc/profile.d/jdk8.sh java -version # 输出1.8.0_202 source /etc/profile.d/jdk17.sh java -version # 输出17.0.2
第三步:清理系统自带的java软链接
好多新手在服务器上装完两个jdk,切换了JAVA_HOME,执行java -version却还是老版本。绝大多数情况下的根因是PATH里有系统自带的/usr/bin/java软链接,优先级比你的JAVA_HOME还高。
先检查:
which java
如果输出是/usr/bin/java,二话不说把软链接删掉:
rm -f /usr/bin/java
然后重新source一下,让JAVA_HOME正式接管。
第四步:给切换建个快捷方式
每次登录都敲source命令确实烦,在~/.bashrc里加上两个别名:
alias jdk8='source /etc/profile.d/jdk8.sh' alias jdk17='source /etc/profile.d/jdk17.sh'
以后登录服务器,敲jdk8就是JDK 8,敲jdk17就是JDK 17,业内专家指出,判断当前生效JDK永远看JAVA_HOME和PATH的顺序,两者冲突时,先被PATH找到的那个说了算,所以别名方案的本质,就是让你主动去控制这个顺序。
Windows服务器装两个jdk环境变量配置
Windows服务器上用安装包装两个JDK,大概率装第二个时把第一个的JAVA_HOME覆盖掉,让人气得想砸键盘。原因就是MSI安装包会往系统环境变量里硬写绝对路径,装一次写一次。
改用解压版,思路跟Linux一致。
解压出两个目录
把JDK 8和JDK 17分别解压到:
D:jdkjdk1.8.0_202
D:jdkjdk-17
建两个变量名,别只用一个
打开系统属性 → 环境变量,在系统变量里新建一个JAVA_HOME_8,指向JDK 8目录;再新建一个JAVA_HOME_17,指向JDK 17目录。
JAVA_HOME本身指向谁,就看你想默认用哪个版本。
PATH里别写死路径
PATH中要么写%JAVA_HOME%bin,要么干脆用带版本名的变量:
%JAVA_HOME_8%bin
以后切换,只改JAVA_HOME_8这个值,或者把PATH里的变量名换一下,你不需要额外记什么jdk版本切换命令,Windows下的核心就是避免写死。
多jdk共存最容易踩的坑
前面聊的都是顺风局,真正让运维头疼的坑藏在下面几类:
- 老项目引用的第三方库编译版本低于JDK 8,硬搬到JDK 17上运行,动不动就NoSuchMethodError
- Tomcat、Jetty这类应用服务器有自己的启动脚本,脚本里写死了jar路径或JAVA_HOME,全局环境变量对它根本无效
- Maven或Gradle构建时,编译器版本跟当前JDK不匹配,报出莫名其妙的兼容性错误
行业共识认为:多JDK共存本身不是麻烦,麻烦的是项目里的中间件各自绑定版本、各自藏着一套配置。
遇到这些情况,不要只切全局JAVA_HOME,去翻对应服务的启动脚本,该在脚本里指定路径就指定路径,别偷懒。
Q&A:一个服务器怎么装两个jdk版本共存问题
问:一个服务器装两个jdk会互相覆盖吗?
不会,JDK本质是一堆文件和目录,只要安装路径分得清清楚楚,它们之间没有任何写入交集,你看到的“覆盖”其实都是环境变量被反复修改导致的假象,JDK文件本身没被谁动过。
问:切换JDK版本后,已经启动的服务需要重启吗?
新起的进程会读取切换后的环境变量,已经在跑的服务不会受影响,想让特定服务用上目标JDK,必须手动重启那个服务,让新进程去加载新环境变量。
问:直接用Docker装不同JDK会不会更省事?
Docker把每个JDK隔离在独立容器里,业务环境更干净,而且JDK镜像体积小,拉起一个实例也就几十秒的事,如果服务器本身已经有容器编排平台,用Docker管理多版本JDK确实比在宿主机折腾环境变量更灵活,没有容器平台的话,老老实实用我上面教的方法,也足够胜任日常任务。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/742717.html





