重复和重叠的类层次结构无缝构建

问题描述 投票:0回答:1

所以我有了这个Scala +多模块Maven项目层次结构:

- pom.xml
- nested1
| - pom.xml
| - src
  | - main
    | - scala
      | - ...
      | - MyClass.scala
      | - ...
- nested2
| - pom.xml
| - src
  | - main
    | - scala
      | - ...
      | - MyClass.scala
      | - ...
- app
| - pom.xml
| - Main.scala

基本上,项目nested1nested2具有完全相同的类层次结构:它们声明相同的类,相同的特征,全部具有相同的内容,等等。

app/pom.xml具有以下依赖性:

<dependency>
    <groupId>${project-package}</groupId>
    <artifactId>nested1</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>${project-package}</groupId>
    <artifactId>nested2</artifactId>
    <version>1.0</version>
</dependency>

Main类实际上在第1行导入了MyClass,但是(我想)它无法确定采用哪个版本:nested1/src/main/scala/${project-package}/MyClass.scalanested2/src/main/scala/${project-package}/MyClass.scala都具有相同的${project-package}

我实际上尝试过这种情况,并且maven似乎随机选择了两个类中的任何一个,甚至没有发出单个警告或错误。

幕后发生了什么?为什么我没有收到“歧义导入语句:MyClass中第1行的Main”之类的错误?

scala maven import
1个回答
1
投票

您不会看到您所描述的错误,因为JVM明确不支持这种情况。它甚至与Scala都不直接相关:它只是在JVM级别上,没有“库”之类的东西,只有平坦的类路径(无论如何直到JPMS),其中类名应该是唯一的。

通常,这种情况应该从不发生-您只能在一个类加载器(或更常见的是在一个类加载器树的单个分支)。如果这样做,则发生的情况是不确定的。这类似于C / C ++中的“未定义行为”的概念:运行时仅假设给定名称只能有一个类,并且可以根据此假设自由地进行操作。根据类加载器的配置,您可以获得随机结果,一些固定结果,类加载过程中的错误或这些的任意组合。当您具有依赖关系,而依赖关系又依赖于同一类的不同版本时,事情变得更加funny,从而导致大量潜在的运行时异常。

这是JVM世界中一个非常著名的问题的一部分,即所谓的classpath/JAR hell。基本上,如果您的项目足够复杂,以至于对同一库的不同版本(或更具体地说,对相同的类名)具有可传递或直接的依赖关系,您将遭受[[will。痛苦的程度取决于您情况的复杂性:在某些情况下,确保在类路径中仅拥有一个版本的库就足够了(这可能需要对构建配置进行一些调整);在其他情况下,则必须对依赖项的某些子集执行shading(这正是解决您遇到的问题的一种方法)。在更困难的情况下,阴影将不起作用,您将不得不重新考虑您的体系结构。根据您的环境,您可能需要使用OSGi或新的Java Platform Module System之类的工具来解决类路径问题。

[请注意,使用JPMS,这种情况会变得更好一些:设计上的Java模块不能在同一JVM加载的多个模块中定义相同的程序包,因此,如果将项目编译为适当的模块,然后尝试使用它们在第三个项目中,您将在启动期间收到有关模块冲突的异常。话虽这么说,我在JPMS方面没有太多经验,所以我不能说它会如何工作,特别是在混合Scala的情况下。
© www.soinside.com 2019 - 2024. All rights reserved.