Eclipse is confused by imports ("accessible from more than one module")

Since I'll bet lots of people will be running into this problem with modular Java, I'll help and give the real answer.

This error happens when

  • you have a dependency in your project
  • that contains code
  • using packages
  • that are also in the modules
  • being referenced by your project

If your project has set the source compatibility to something like Java 12, it will start enforcing the rule, that has been there all along in Java:

"Don't use packages that belong to the JDK in your own code."

Unfortunately, lots of developers and vendors have done that over the years. Can't do that anymore.

If you set your project to Java 12 source compatibility, Eclipse adds the JDK modules which include everything "java.*" and "javax.*" and even "jdk.*", "org.w3c.*". These packages may be in use by your dependencies or their transitive dependencies.

How to fix

You need to:

  • look at which package its complaining about
  • and expand the "Projects and External Dependencies" node in the Package Explorer.
  • Find out which dependency is using that package.
  • Then you can simply exclude that dependency from your project.

Or you could get the source of that dependency, if available, and rebuild the jar with changed packages. Otherwise you have to remove that dependency and find a replacement for that technology. Pain huh?

If its a transitive dependency you can often just exclude it. Here is an example of that for Gradle based projects.

GradleConfig.xml:

configurations {
   all*.exclude group: 'xml-apis'
}

This is caused by

  • a JAR on the Classpath that contains the package java.awt that also exists in the system library but the
  • JRE System Library is on the Modulepath

In the Java Platform Module System (JPMS) it is not allowed to use the same package in more than one module. If the Modulepath and the Classpath is used, everything on the Classpath is handled as the <unnamed> module (in your case the package java.awt exists in the system module java.desktop and also via the JAR on the Classpath in the module <unnamed>).

Since the JRE System Library cannot be moved from the Modulepath to the Classpath (see this answer by Stephan Herrmann for details), you only have the following options:

  • Set the compiler compliance to 1.8 (as you already mentioned)
  • Rebuilt the JAR to avoid Java system library package names inside the JAR (if reflection is used, additional code changes may be necessary):
    • If you have the source code, change the package names (e.g. change the package and subpackae java to java_util and javax to javax_util) and recreate the JAR
    • If you have only the .class files you have to decompile the .class files first

Tags:

Java

Eclipse

Jar