[JLBP-5]

Do not include a class in more than one classpath entry

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.

When a class appears in more than one location in the class path, it is unpredictable which version is loaded at runtime. Indeed this can change depending on how the POMs are set up. If the overlapping classes are not identical—for example, one version has methods the other does not, or one has fixed bugs the other hasn’t—this leads to confusing, hard-to-diagnose bugs.

This can happen in several ways:

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 with guava. Build systems such as Maven and Gradle cannot deduplicate guava-jdk5 with 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 (javax.servlet:javax.servlet-api:3.1.0 and javax.servlet:servlet-api:2.5 at least). The correct choice depends on the runtime.

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.