Definition: When the same fully qualified class name is provided by two or more distinct artifacts (different group IDs, different artifact IDs, or both) the classes are said to overlap.
This can happen in several ways:
A library has published the same classes in artifacts with different group ID or artifact IDs.
A third party forks a library under their own group ID but does not repackage the classes.
A third party library copies an existing library’s packages into its own jar file without shading the dependency. This case is particularly insidious since it may not be obvious that there’s an unexpected, undocumented version of the classes hiding inside the seemingly unrelated jar.
Example 1: Guava’s main artifact ID is
guava, but from versions 13.0 to 17.0,
Google also published a
guava-jdk5 artifact with classes that overlapped
guava. Build systems such as Maven and Gradle cannot deduplicate
guava because the artifact names are different.
When both artifacts appear in the classpath, users encounter
runtime errors resulting from classes and methods not being found.
Example 2: There are multiple artifacts that provide classes under
javax.servlet:servlet-api:2.5 at least). The correct choice
depends on the runtime.
servlet-apiis one used exclusively in servlet applications. In this case, the
servlet-apidependency should have
providedscope. Other libraries should not depend on
servlet-api. For example, do not use constants such as
javax.servlet.http.HttpServletResponse.SC_FORBIDDENif your library might be used anywhere that is not a servlet. Define these status codes yourself or choose a different library to provide them.
In Java 9 and later overlapping classes become compile-time and runtime errors when named modules are used. It is critical, especially in Java 9 and later, to remove all but one of the artifacts that contain overlapping classes from the classpath. Generally this requires changing the POMs of multiple Maven artifacts so they no longer include any dependencies on the artifacts you need to remove from your project’s classpath.
If this isn’t possible, for instance because a dependency that imports an undesired artifact is unmaintained, then add dependency exclusions for the artifacts you wish to remove in your own project’s pom.xml.