Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Maven:一个JVM中的不同库版本_Java_Maven - Fatal编程技术网

Java Maven:一个JVM中的不同库版本

Java Maven:一个JVM中的不同库版本,java,maven,Java,Maven,我有一个项目,它的依赖关系树很大,也就是说,它包含了来自多个团队的模块 现在有一些常用的依赖项,这些依赖项在多个模块中很常见 一个简化的例子可以是: TopModule.jar ChildModule.jar CommonModule-v1.jar CommonModule-v2.jar 当我构建我的项目时,我指定了最新版本的通用依赖项,但是很难要求其他团队也这样做 因此,TopModule通常使用CommonModule的不同版本(上例中的v1和v2)构建 我的问题是: 如果

我有一个项目,它的依赖关系树很大,也就是说,它包含了来自多个团队的模块

现在有一些常用的依赖项,这些依赖项在多个模块中很常见

一个简化的例子可以是:

TopModule.jar
  ChildModule.jar
    CommonModule-v1.jar
  CommonModule-v2.jar
当我构建我的项目时,我指定了最新版本的通用依赖项,但是很难要求其他团队也这样做

因此,TopModule通常使用CommonModule的不同版本(上例中的v1和v2)构建

我的问题是:

如果最终的jar文件同时包含CommonModule-v1.jar和CommonModule-v2.jar,它将如何影响运行时


运行时是否会在需要v1的地方错误地加载v2版本,反之亦然?

如果pom.xml只是已打包模块的聚合器,则这一点适用。如果情况并非如此,并且您的项目实际上将所有这些模块编译并打包为子模块,那么maven将选择一个。如果它自己编译每个项目,那么它将使用该依赖项进行打包。但是,如果它们最终都在同一个类加载器中,那么它将无法正常工作

在运行时,它可能会导致错误,比如
找不到方法
等等。您的字节码类已编译并与正确的依赖项链接,但由于类装入器找到了两个候选类,因此它只在运行时装入一个

您可以做的是设置一个定义
的父pom,然后要求所有团队将其用作父pom,不要声明
,而是从父pom.xml继承它


参考资料

这取决于模块在maven中的命名方式。通常,maven尝试解决冲突的lib,并将最高版本放入树中。但是,如果这些库在artifactId方面是不同的工件,那么maven将看不到它们来自同一品种,因此无法解决歧义

通常通过公共parent.pom解决此问题,在该文件中定义整个项目中常用库的版本。如果您无法控制其他项目(不是构建的一部分,只是依赖项),那么您可能很幸运最终的项目运行良好。如果库在较新版本中破坏了兼容性,您将无法使用它


那么,您的最终项目是否包含库的两个版本,您检查了吗?依赖关系树可能会显示两个版本,但如果maven只使用层次结构中依赖关系的最新版本,那么maven最终只会使用每个工件的一个版本——它不会做任何奇特的类装入器隔离技巧。您可以看到它将与
mvn依赖项:resolve
一起使用哪个版本


如果需要在依赖项中使用特定版本,可以使用。它将执行重命名技巧,以便依赖项获得它们自己的库版本。

Classloader将加载出现在类路径上的第一个JAR。更详细地说,它将搜索类路径上的第一个类,因此在每种情况下,所有这些搜索都将分为
CommonModule-v2.jar
。所以答案是肯定的-如果v1出现在类路径的前面,它可能会错误地加载v2版本。要在全局范围内解决此问题,请使用此选项

此规则要求依赖项版本号聚合。如果 项目有两个依赖项,A和B,它们都依赖于同一个项目 工件C,如果A依赖于不同的 C的版本然后B依赖C的版本


org.apache.maven.plugins
maven enforcer插件
1.3.1
执行
执行

在这之后,所有团队都使用一致版本的依赖项一起工作。

在@yshavit所说的基础上,理想情况下,您应该排除早期版本的
CommonModule
,这样类路径中只有v2。只有当
CommonModule
v2 api与
CommonModule
v1向后兼容时,这才可能实现

以下是如何排除的示例:

    <dependency>
        <groupId>ChildModuleGroupid</groupId>
        <artifactId>ChildModuleArtifactid</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>CommonModuleGroupId</groupId>
                <artifactId>CommonModuleArtifactId</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

子模块组
儿童模块化激活
1
CommonModuleGroupId
公共模块化激活

您应该将其放在TopModule pom.xml中。

您所说的“最终jar文件同时包含
CommonModule-v1.jar
CommonModule-v2.jar
”是什么意思?你通常不会把罐子装在其他罐子里。你的问题对于Java应用程序的普遍部署方式没有多大意义。(其中包含类路径中某个位置的所有可传递依赖项的平面列表。)Maven将使用最新版本,您可以尝试dependency:analyze duplicate。@millimoose,欢迎使用maven@user2250246我很了解Maven,你所描述的并不是Maven的工作方式。对于一个
mvn包
,它只会对给定模块的类文件进行JAR处理,在编译之后它不会处理依赖项。如果您正在进行WAR,那么它会将依赖项放入
WEB-INF/lib/
,但在这种情况下,它会选择其中一个版本,而不是两个版本。(除非不同的版本有不同的
groupId
+
artifactId
,这并不是Maven能够自动处理的东西。)那么,与其说你很油嘴滑舌,不如说你描述了实际发生的事情;dr:Maven默认情况下不会将
jar
s放入其他
jar
s中。如果你有,发布相关的配置。Maven将在一个构建中发现两个JAR版本时自动只选择一个版本<代码>是决定哪个版本的方法。他说,将模块打包在一起。这些模块可能已经打包。但这只是一个猜测。
    <dependency>
        <groupId>ChildModuleGroupid</groupId>
        <artifactId>ChildModuleArtifactid</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>CommonModuleGroupId</groupId>
                <artifactId>CommonModuleArtifactId</artifactId>
            </exclusion>
        </exclusions>
    </dependency>