简体   繁体   中英

Duplicated and superposed class hierarchy seamlessly builds

So I've got this Scala + multi-module Maven project hierarchy:

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

Basically, the projects nested1 and nested2 have exactly the same class hierarchy: they declare the same classes, the same traits, all of them have the same content, etc.

app/pom.xml has these dependencies:

<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>

The Main class actually imports MyClass at line 1, but (I would guess) it has no way to tell which version to take: both nested1/src/main/scala/${project-package}/MyClass.scala and nested2/src/main/scala/${project-package}/MyClass.scala have the same ${project-package} .

I actually tried this scenario, and maven seems to choose at random either of the two classes without even issuing a single warning or error.

What's happening behind the scenes? Why am I not getting an error like "ambiguous import statement: MyClass at line 1 in Main "?

You don't see errors like you describe because this situation is explicitly not supported by the JVM. It is not even related to Scala directly: it's just on the JVM level, there is no such thing as "libraries", there is only flat classpath (until JPMS in any case), where class names are supposed to be unique.

In general, such situation should never happen - you just can't have different classes having the same fully-qualified name (package + class name, basically) within one class loader (or, more often, within a single branch of the tree of classloaders). If you do, what happens is undefined. This is similar to the concept of "undefined behavior" in C/C++: the runtime just assumes that there can only be one class for the given name, and is free to behave based on this assumption; depending on classloaders configurations, you can get a random result, some fixed result, an error during classloading, or any combination of these. Things become even more funny when you have dependencies which in their turn depend on different versions of the same class, resulting in a whole host of potential runtime exceptions.

This is a part of a very well-known problem of the JVM world, so-called classpath/JAR hell . Basically, if your project is complex enough that it has transitive or direct dependencies on different versions of the same library, or, more specifically, the same set of class names, you will suffer. The amount of suffering depends on the complexity of your situation: in some cases, ensuring that you only have one version of a library in classpath is enough (which might require some tweaks in the build configuration); in other cases, you'll have to perform shading (which is exactly a way to solve the problem which you encountered) for certain subset of your dependencies. In even more difficult cases, shading won't work, and you'll have to rethink your architecture. Depending on your environment, you might need to use tools like OSGi or indeed the new Java Platform Module System to solve classpath issues.

Note that with JPMS, this particular situation becomes a bit better: Java modules by design cannot have the same package defined in a multiple modules loaded by the same JVM, so if you compile your projects as proper modules, and try to use them in the third project, you'll get an exception during startup about conflicting modules. That being said, I don't have much experience with JPMS so I can't say how exactly it will work, especially with Scala in the mix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM