【问题标题】:How does java choose between a method with same name, parameters and class in different dependencies?java如何在不同依赖的同名、同参数、同类的方法之间进行选择?
【发布时间】:2022-02-01 00:04:28
【问题描述】:

我们最近遇到了一个场景,我们有两个公司依赖项,每个依赖项都有一个具有相同名称、参数和类的特定方法,可能是复制粘贴。在我的实际微服务中,这两个依赖项都被声明为直接依赖项。

想象一下:

-- Microservice
    |-- Corporate dependency A
        |-- com.enterprise.project.UtilityClass
            | public static String someMethod(String someParameter)
    |-- Corporate dependency B
        |-- com.enterprise.project.UtilityClass
            | public static String someMethod(String someParameter)

我们注意到了这个问题,因为当我们添加第二个依赖项时,maven 在我们的构建中报告了它,我们检查并认为输出是相同的,它们的实现略有不同。我的问题是,JVM 如何决定在运行时使用哪种方法?

【问题讨论】:

    标签: java


    【解决方案1】:

    在“通常”情况下,例如,您在应用程序的启动脚本中提供了一个 -classpath 属性,它包含一个“已知”的 jar 列表。现在,如果UtilityClass 驻留在A.jarB.jar 中,这些jar 在类路径中的出现顺序将决定将加载哪个类实现:

    例子:

    java -classpath A.jar B.jar <whatever>
    

    表示将加载来自A.jarUtilityClass,只是因为它先出现。

    现在,当您通过 maven 运行时,事情变得更加复杂,因为它自己管理 -classpath。从 maven 2.0.9 开始,它使用 pom.xml 中的 order 作为类路径(例如,参见 here)。

    如果您有更多“高级”加载 jar 的方法(如自定义类加载器,那么答案可能会有所不同)...

    无论如何,最好的方法可能是提出一个依赖项并尽可能排除另一个。

    【讨论】:

    • 既然 Maven 使用声明依赖项的顺序,为什么如果知道将使用第一个声明的依赖项,它会发出诸如“不可预测的运行时行为”之类的警告?
    • 我的意思是,如果您通过 maven 运行测试或其他东西,但是,毕竟,maven 只是一个构建工具。在生产中,您将拥有一个在类路径中登记两个 jar 并且根本不使用 maven 运行的工件......
    • 是的,这实际上是我的问题,我的生产环境中的 JVM 是如何决定使用哪种依赖项的哪种方法的?如果您知道 JVM 行为,您能否编辑您的答案?
    • 我不能——这完全取决于你在生产中运行什么以及如何运行......如果你有一个“传统”工件——某处必须有一个运行应用程序的脚本,并且还设置了“-classpath”,对吧?我不知道是谁“准备”了这个脚本,所以你应该检查你的应用程序......另一个用例是如果你有自定义类加载器,比如在 spring boot 中。那我想会是由boot-inf/lib中jar的顺序来决定的……有很多可能的情况。但总而言之,我认为你不应该“假设”运行同一类的 2 个版本是可以的——它很容易出错
    • 我们使用spring-boot,所以也许lib中的命令实际上是这样做的,我认为不是因为Maven发出的警告。我认为这确实是JVM本身解决的问题。我们已经要求其中一个公司团队排除重复的类并使用原始依赖项作为自己的依赖项。
    【解决方案2】:

    这将取决于哪个依赖项首先出现在类路径上。

    【讨论】:

    • 如何保证 maven 本身将其报告为具有不可预测的运行时行为的运行时问题场景?
    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 2016-05-01
    • 2022-11-14
    • 1970-01-01
    相关资源
    最近更新 更多