序言
在docker容器中有时会遇到一些特别奇怪的问题.这里整理记录一下我觉得奇怪的问题cuiyaonan2000@163.com,持续更新
替换JDK不生效
一般来说我们替换一个自带jdk镜像的jdk版本的时候只需要设置
bash
export JAVA_HOME=/opt/java/jdk8
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
因为我们之前在非容器的系统上就是这么设置的,但是在容器中可能会发现替换总是不成功,在运行是java 总是指向原来的java版本.cuiyaonan2000@163.com
为什么常规配置会失效
1. PATH 只负责"找到门",不负责"进门后做什么"
- 作用 :
PATH告诉系统去哪里找java这个可执行文件。 - 现状 :你的
PATH已经配对了,系统成功找到了/opt/java/jdk8/bin/java这个文件(那个 15KB 的启动器)。 - 局限 :一旦程序开始运行,
PATH的任务就结束了。它管不了程序运行时需要加载哪些.so动态链接库。
2. JAVA_HOME 只是给应用看的"路标"
- 作用:这是一个约定俗成的变量,告诉 Maven、Tomcat 等工具 JDK 装在哪。
- 局限 :操作系统底层的加载器并不直接读取
JAVA_HOME。除非程序内部写了代码去读取这个变量并手动拼接路径,否则操作系统根本不知道它的存在。
3. LD_LIBRARY_PATH 才是操作系统的"导航仪"
- 作用 :这是操作系统层面的环境变量。当那个 15KB 的启动器试图加载 JVM 核心库时,它会直接问操作系统:"嘿,
libjvm.so在哪?" - 机制 :操作系统会优先检查
LD_LIBRARY_PATH。- 如果不设 :操作系统按默认顺序找,结果找到了系统自带的 JDK 21 的库 -> 版本错误。
- 如果设了 :操作系统在你的指引下,找到了 JDK 8 目录下的库 -> 版本正确。
4. 解决方案
bash
// 将 JDK 8 的库路径放在最前面,强制覆盖系统默认路径
LD_LIBRARY_PATH = "/opt/java/jdk8/lib/amd64:/opt/java/jdk8/lib/amd64/server:${env.LD_LIBRARY_PATH}"