考虑一个 java 程序从 jar 文件中导入类的场景。如果同一个类驻留在两个或多个 jar 文件中,则可能会出现问题。
在这种情况下,程序导入的类是什么?是时间戳较旧的类吗?
我们可以遵循哪些做法来避免此类并发症。
编辑:这是一个例子。我有 2 个 jar 文件 my1.jar 和 my2.jar。这两个文件都包含 com.mycompany.CrazyWriter
考虑一个 java 程序从 jar 文件中导入类的场景。如果同一个类驻留在两个或多个 jar 文件中,则可能会出现问题。
在这种情况下,程序导入的类是什么?是时间戳较旧的类吗?
我们可以遵循哪些做法来避免此类并发症。
编辑:这是一个例子。我有 2 个 jar 文件 my1.jar 和 my2.jar。这两个文件都包含 com.mycompany.CrazyWriter
默认情况下,ClassLoader使用按顺序搜索的类路径加载类。
如果您有同一个类的两个实现,则类加载器首先找到的那个将被加载。
如果这些类实际上不是同一个类(名称相同但方法不同),则在尝试使用它时会出现异常。
您可以使用多个类加载器在单个 VM 中加载两个具有相同名称的类。OSGI框架可以为您管理许多复杂性,确保加载正确的版本等。
首先,我假设您的意思是同一个类驻留在另外两个jar文件中......
现在,回答你的问题:
-bootclasspath
.编辑:解决对此答案的评论之一。我最初认为密封 jar会有所不同,因为理论上它不应该从不同 jar 文件的同一个包中加载两个类。然而,经过一些实验,我发现这个假设并不成立,至少对于默认的安全提供程序。
ClassLoader 负责加载类。它扫描 ClassPath 并加载它首先找到的类。如果您在 ClassPath 上有两次相同的 Jar,或者如果您有两个包含同一类的两个不同版本的 Jar(即 com.packagename.Classname),则会加载第一个找到的 Jar。
尽量避免在类路径中使用相同的 jar 两次。
不知道您所说的“同一个班级还有两个班级” 是什么意思
如果您的意思是内部/嵌套类,则应该没有问题,因为它们位于不同的名称空间中。
如果您的意思是在另外两个 JAR 中,正如已经回答的那样,则使用类路径中的顺序。
如何避免?
一个包应该只在一个 JAR 中以避免重复的类。如果两个类具有相同的简单名称,例如java.util.Date
and java.sql.Date
,但在不同的包中,它们实际上是不同的类。您必须使用至少来自其中一个类的完全限定名称来区分它们。
如果您在查找正在使用的类的哪个版本时遇到问题,那么 jwhich 可能有用: http ://www.fullspan.com/proj/jwhich/index.html
如果同一个类驻留在另外两个 jar 中,则应该有问题。
你到底是什么意思?为什么这会是个问题?
在这种情况下,程序导入的类是什么?(具有较旧时间戳的类??)
如果一个类存在于两个 JAR 中,则将从找到它的类路径上的第一个 JAR 加载该类。引用设置类路径(引用部分也适用于存档文件):
指定多个类路径条目的顺序很重要。Java 解释器将按照类路径变量中出现的顺序在目录中查找类。在上面的示例中,Java 解释器将首先在目录中查找所需的类
C:\java\MyClasses
。只有在该目录中找不到具有正确名称的类时,解释器才会在该C:\java\OtherClasses
目录中查找。
换句话说,如果需要特定的顺序,那么只需在类路径中显式枚举 JAR 文件。这是应用服务器供应商通常使用的东西:要修补产品的特定类,您将包含已修补类的 JAR(例如CR1234.jar
)放在主 JAR(例如weblogic.jar
)之前的类路径上。
我们可以遵循哪些做法来避免此类并发症。
好吧,显而易见的答案是不要这样做(或者只是像上面给出的示例那样故意)。