Java 在类路径中包含两个相同的jar时JVM如何工作

Java 在类路径中包含两个相同的jar时JVM如何工作,java,Java,这是我同事的一个错误:有一个名为test.jar的jar,他已经修复了其中的一个bug。然后他重新编译代码并构建了一个名为testnew.jar的新jar 问题是他将这两个jar放在一个文件夹中,该文件夹位于类路径中。 所以当程序运行时,行为是一种混乱。我不知道发生了什么,但在删除test.jar之后,一切又恢复了正常 所以我想知道JVM的行为是什么。它是否在遇到的第一个jar中使用类文件?还是别的什么 谢谢。是的,默认情况下它使用第一个jar中的类。这就是为什么您必须检查库目录中是否有重复项。

这是我同事的一个错误:有一个名为test.jar的jar,他已经修复了其中的一个bug。然后他重新编译代码并构建了一个名为testnew.jar的新jar 问题是他将这两个jar放在一个文件夹中,该文件夹位于类路径中。 所以当程序运行时,行为是一种混乱。我不知道发生了什么,但在删除test.jar之后,一切又恢复了正常

所以我想知道JVM的行为是什么。它是否在遇到的第一个jar中使用类文件?还是别的什么


谢谢。

是的,默认情况下它使用第一个jar中的类。这就是为什么您必须检查库目录中是否有重复项。对于我和我的同事来说发生了很多次。

如果有重复的,它会读取在类路径中首先出现的一个

编辑 类路径文件通常如下所示

<classpath>
        <classpathentry kind="lib" path="C:/Temp/test.jar"/>
        <classpathentry kind="lib" path="C:/Temp/testnew.jar"/>
    <classpathentry kind="output" path="build/classes"/>
</classpath>

如果您的类路径类似于上面的内容,那么JVM将首先查看test.jar,就像它在类路径中首先出现一样。如果您想自己测试它,请尝试将testnew.jar的classpathentry移到test.jar条目之上。您将看到它现在引用testnew.jar而不是test.jar


参考资料:

据我所知,它还没有定义

Java有一个可插拔的类加载器系统,因此知道将会发生什么的唯一方法是查看的文档,可能特别是,它没有为此定义行为,并且查看和的相关部分,这两个部分似乎都没有在这方面指定类加载器的约束。因此,除非web容器使用的类加载器记录了该行为,否则您无法确定将加载哪个类


很可能第一个找到的与类的二进制名称匹配的将是加载的,但是我们假设的行为与指定和/或记录的行为之间有很大的区别。

JVM加载类路径上的任何特定JAR。自Java6以来,还有一种通配符表示法。下面是几个例子

java -cp ".:lib/example.jar" Main
以上内容将只加载在当前目录和example.jar中找到的类。而下一个示例将使用任何jar从中加载类

java -cp ".:lib/*" Main
我不认为定义了首先检查目录中哪个jar以查找类的顺序,而只是定义了操作系统在列出文件时给出的顺序


很可能您的IDE(或运行程序所用的任何东西)正在使用后一种符号来运行程序。你可以更改它,使其使用前者,但如果你更改一个罐子的名称或添加新的罐子,它会破裂。

因此,似乎没有任何机制可以避免这种情况。这是一个有趣的假设,但你有任何参考来支持它吗?@逍遥避免这种情况的方法是不添加相同的东西两次。如果你复制相同的东西,它有一个定义的行为,所以它不一定是一个问题。我很确定这属于“未定义的行为”的标题。记住,并不是每个人都在使用SUN JVM,即使他们在使用,也不能指望每个版本都是相同的!我相信官方的唯一一件事是,一旦它找到一个类(或者没有找到它),它将不会再检查一次,即使你在运行时添加jar文件,那么你就不能依赖它了。据我所知,除了
java
工具本身(它记录了它的搜索计划)之外,它是未定义和未记录的行为。你对此有参考资料吗?@T.J.Crowder:嗯,我没有书面证据证明这一点,但我自己已经测试过了。这是我观察到的默认行为。看到我上面的编辑,我做了一些类似的事情来证明它。
@Shashank
:那么你不能相信这种行为,它可能会因类加载器的不同而有所不同,甚至在使用同一类加载器的情况下,如果它使用了一些奇怪的查找方法,它也会有所不同。有关详细信息,请参阅我的答案。我在java文档中找到了。请参阅“Java Launcher如何查找JAR类路径类”一节……我认为它说,JAR类路径中出现的JAR文件是在任何早期的类路径条目之后搜索的,在类路径后面出现的任何条目之前……那么,你不认为这将是查看类路径的默认行为吗?@ShashankKadne:很好,这告诉了你
java
工具(java启动器)的功能(至少,它在10年前的v1.4.2中做了什么;但我怀疑它是否改变了)。这在使用
java
工具时非常有用。它通常不会告诉您类装入器将做什么。OP没有说明它是什么类型的应用程序(通过
java
启动的桌面应用程序,类加载器由容器定义的web应用程序,等等)。@shashashankakadne我相信你的链接已经找不到了,所以在这里添加了更新的链接。。