Java 冲突依赖:如何选择?

Java 冲突依赖:如何选择?,java,maven,Java,Maven,让我们以项目a及其依赖项(包括可传递依赖项)为例。如果我查看依赖关系树,我会看到在一条路径的末尾,我有slf4j api:1.6.4,在另一条路径的末尾,我有slf4j:1.6.1 我必须选择哪种依赖关系?如果我选择slf4j:1.6.4,我的类路径上就没有版本1.6.1,我如何知道版本1.6.4是否与使用版本1.6.1的代码兼容 我不明白,因为最后我的类路径上只有一个slf4j版本 谢谢这是一个被称为“Jar地狱”的老问题,与C/C++中的“DLL地狱”有关 对于可转换依赖项,您无法控制版本控

让我们以项目a及其依赖项(包括可传递依赖项)为例。如果我查看依赖关系树,我会看到在一条路径的末尾,我有slf4j api:1.6.4,在另一条路径的末尾,我有slf4j:1.6.1

我必须选择哪种依赖关系?如果我选择slf4j:1.6.4,我的类路径上就没有版本1.6.1,我如何知道版本1.6.4是否与使用版本1.6.1的代码兼容

我不明白,因为最后我的类路径上只有一个slf4j版本


谢谢

这是一个被称为“Jar地狱”的老问题,与C/C++中的“DLL地狱”有关

对于可转换依赖项,您无法控制版本控制,也无法保证不同版本的兼容性。在记录器中发生微小版本更改的简单情况下,它们很可能兼容。但是,在一般情况下,你会遇到冲突

它的开发部分是为了解决这个问题。我个人使用OSGi实现

问题源于Java类加载器。它不能加载具有相同包和类名的两个类,这意味着它不能加载两个版本的slf4j以满足您的约束

OSGi是一个运行在JVM之上的运行时框架。与使用默认类加载器直接在JVM上运行Jar不同,您可以在OSGi实例中运行Jar。 这需要在Jar的清单文件中添加一些元数据,这些Jar称为bundle。
OSGi为每个包提供了自己的类加载器,允许分离可传递的依赖项。每个依赖项都是独立的捆绑包,能够在其捆绑包的独立类加载器中加载slf4j的版本,而不会发生命名冲突。

Maven旨在管理此类可传递的依赖项,并确保类路径上只存在一个版本的jar

如何了解Maven在做什么 该插件将演示Maven代表您所做的事情(遍历各种POM并确定还有谁声明了对相同模块的依赖关系)

通常选择模块的最新版本,这是有意义的,因为某些模块可能使用的方法仅在最新版本的日志库中可用。在实践中,当依赖代码没有保持在锁定状态时,通常是删除不推荐的方法导致编译问题

如何告诉Maven该做什么 如果希望对所选版本有更多的控制权,则需要指定一个依赖项版本范围,如下所示:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>[3.8,4.0)</version>
    <scope>test</scope>
</dependency> 

朱尼特


  • 希望这有帮助。

    我不同意。Maven通过确保类路径上只存在一个jar来避免“jar地狱”。Maven文档说明了如何通过说明版本范围来控制这些版本。实际上,我从来没有使用过这个特性。OSGi是一项伟大的技术,但它解决了部署依赖关系管理问题。提出的问题涉及构建时依赖关系管理,特别是使用Maven。@MarkO'Connor确保类路径上只存在一个jar在一定程度上帮助了我。如果一部分代码使用1.0版(而不是2.0版)上的特定API,而另一部分代码使用2.0版(而不是1.0版)上的特定API,它如何工作?@MarkO'Connor“总之,这不是Maven的错,这正是OSGi提供的第三方模块管理。最简单的测试是“是否编译”。这肯定会解决不推荐使用的API的潜在问题。运行时兼容性更具挑战性(在Java中,某些库仅在运行时链接)。解决方法是一组全面的单元和/或功能测试。
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>[3.8,4.0)</version>
        <scope>test</scope>
    </dependency>