Bar*_*lom 5 java classpath classloader urlclassloader docker
我正在 Docker 映像中运行 Java 服务,其执行如下操作:
java -server -cp 'libs/*'
奇怪的是,我发现它会在我的本地计算机上启动,但不会在开发服务器上启动,在开发服务器上它会给出NoSuchMethodError.
经过一番挖掘,我发现 libs 目录中同时存在 JPA 2.0 和 2.1 版本。虽然这本身就是一个问题(并且很容易修复),但它并不能解释不一致的原因,所以我决定打印出来:
(ClassLoader.getSystemClassLoader() as URLClassLoader).urLs
.forEach(::println) // kotlin
Run Code Online (Sandbox Code Playgroud)
我发现两台机器上的库顺序不同。然而,在同一台机器上后续运行的图像之间是一致的,所以不是随机的。
虽然我现在知道为什么镜像无法在开发服务器上启动,并且我可以解决手头的问题,但它确实让我想知道:为什么这个顺序在 Docker 主机上不一致?可复现性和一致性不正是Docker的要点之一吗?类路径的顺序是否取决于 IP、主机名或安装的主机目录(在不相关的位置)等挑剔的事物?
小智 1
我刚刚遇到这个问题,并注意到 JVM 使用一种解析类路径上的通配符的方法,该方法不提供任何排序保证。
请注意,它使用对 readdir 的调用来迭代通配符表示的内容,并且readdir不保证任何特定顺序:
连续调用 readdir() 读取文件名的顺序取决于文件系统的实现;这些名字不太可能以任何方式排序。
您可以通过在类路径上显式对 jar 进行排序而不是使用通配符来避免排序问题。在我们的例子中,我们在发现主机系统中从 readdir 产生不同结果的特定差异之前删除了重复的 jar。
| 归档时间: |
|
| 查看次数: |
469 次 |
| 最近记录: |