In Eclipse, what is the difference between modulepath and classpath?

In Eclipse, what is the difference between modulepath and classpath, and which one should I use to add a JAR file in the lib folder?

And why does the JRE System Library appear in modulepath?


The module system has mainly the following impact on the code:

  • A package can only be accessed from one module (Nested packages are treated as separate, so even though the package java.util is in the module java.base, the package java.util.logging can be in the module java.logging)
  • You can only access public fields and methods of code in exported packages of other modules. This is true even with reflection (i.e. java.lang.reflect.AccessibleObject.setAccessible(boolean) only works for code in the same module)

All code that is on the classpath lives together in the "unnamed" module. All code on the modulepath lives in their own "named" modules.

You have to distinguish two cases:

  • If you don't add a module-info.java to your project, your project will be part of the unnamed module and can see all other code in the unnamed module, plus code in java.base and code in modules in java.se root module. Basically this means that w.r.t. code on the classpath, everything still works as in Java 8, so you should just put your dependencies on the classpath.

  • If you have a module-info.java in your project, your project will be in its own named module and can only see code in java.base and other named modules which are references using "requires"-clauses in the module-info.java. As named modules are only found via the module path, you should put your dependencies on the module path. This even works for jars created before Java 9, which will get a module name derived from the .jar file name (in which case they are called "automatic" module).

The JRE is always on the module-path, so that its internal code cannot be accessed even from code on the classpath.

There is one special case: If you have a module-info.java in your project and have test code in your project, you usually don't want to mention test dependencies like junit in the module-info.java. There are two solutions for this:

  • Create a dedicated test module. This has always been the convention for osgi-based projects. Disadvantage is that you can only use public API in your tests

  • The solution used by Maven: Put your test dependencies on the classpath. When compiling test code, Maven adds command line options that allow the code in the named module to read the unnamed module (which is not possible via the module-info.java).

In Eclipse Oxygen, the Maven solution was not possible, because it has no notion which code is test code, but this has been implemented in the upcoming Eclipse Photon (4.8) release, which will be out in June. You can already work with the (feature-complete) milestone builds from http://download.eclipse.org/eclipse/downloads/. In case you find any bugs, please report them at https://bugs.eclipse.org/bugs/.