2

What are the potential problems when using a valid modular jar (which contains a module-info.class) on the class-path of a non-modular application instead of on the module-path? There are only two possible problems that come to my mind at the moment:

  1. Accidental use of fields, methods or resources due to lack of encapsulation.
  2. ServiceLoader problems due to missing or inconsistent service provider declarations in META-INF/services.

Are there any other potential problems that I just don't see at the moment?

mipa
  • 10,369
  • 2
  • 16
  • 35
  • Missing dependencies at runtime. – Johannes Kuhn Nov 10 '19 at 15:57
  • @JohannesKuhn Good point, but I am assuming that in a non-modular application you have to manage your dependencies yourself anyway. Either manually or via a build tool like Maven/Gradle. – mipa Nov 10 '19 at 16:05

1 Answers1

1

I don't think any of those things you mentioned will be the case. Quoting an excerpt from the book (I hope I'm allowed to do this) The Java Module System by our very own honorable member, @Nicolai, on the topic of how the classpath works since java 9:

Emphasis Mine

Taking this backward compatibility into account, the question remains how the module system deals with types on the class path. In short, they all end up in the unnamed module, which the module system spins on the fly. This is a regular module, but it has some peculiarities, one of which is that it automatically reads all resolved modules. This is also true for modules that end up on the class path—they’ll be treated just like plain JARs, and their types will end up in the unnamed module as well, ignoring whatever their module declaration has to say. The unnamed module and modules on the class path are part of the migration story, which section 8.2 tells in full detail.

Once again in section 8.2.2

One detail that’s a little counterintuitive and easy to get wrong is what constitutes the unnamed module. It seems obvious that modular JARs become modules and hence plain JARs go into the unnamed module, right? As explained in section 8.1.3, this is wrong: the unnamed module is in charge of all JARs on the class path, modular or not. As a consequence, modular JARs aren’t bound to be loaded as modules! If a library starts delivering modular JARs, its users are by no means forced to use them as modules. Users can instead leave them on the class path, where their code is bundled into the unnamed module. As section 9.2 explains in more detail, this allows the ecosystem to modularize almost independently of one another.

Finally section 8.1.3 states:

The class path makes no distinction between plain and modular JARs: if it’s on the class path, it ends up in the unnamed module. Similarly, the module path makes little distinction between plain and modular JARs: if it’s on the module path, it ends up as its own named module. (For plain JARs, the module system creates an automatic module; for modular JARs, it creates an explicit module according to the description.)

Conclusion

Nothing happens. If the modular jar is on the classpath, it will be implicitly lumped into the unnamed-module and readable by anyone. Moreover, anything on the classpath can read everything else. Also the modular jar will behave just like any jars prior to the module system in that public parts will be visible to all and private parts are still visible by reflection.


Edit 2019/11/11

Services in modular jars need to be declared in META-INF/services as well as in the module-info.java, if they are to be used from the classpath. This is what the book has to say:

Modular JARs on the module path are the sweet spot for services in the module system, so they work without limitations. On the class path, modular JARs can cause problems, though. They’re treated like plain JARs, so they need entries in the META-INF/services folder. As a developer whose project relies on services and whose modular artifacts are supposed to work on both paths, you need to declare services in the module descriptor and META-INF/services.

...

If a modular JAR is supposed to provide services even if placed on the class path, it also needs entries in the META-INF/services directory. For each provides ${service} with ${provider} directive, create a plain file called ${service} that contains one line per ${provider} (all names must be fully qualified).

Adendum

In addition to the conclusion above, library authors with services in modular jars need to also declare those services in META-INF/services if the jar is to be used on the classpath.

smac89
  • 39,374
  • 15
  • 132
  • 179
  • All what you have said and cited does not refer to service detection and loading. On the classpath a service is provided via an entry in META-INF/services/ whereas on the module path it is provided via an entry in module-info.java. I just confirmed again in a test that a service is not found when you put a modular jar onto the classpath and it does not also have a valid entry in META-INF/services in addition to the one in module-info.java. – mipa Nov 11 '19 at 12:02
  • @mipa the service also has to be declared in `META-INF/services` in addition to `module-info.jar` for the jar to be used on the classpath. See my edit – smac89 Nov 11 '19 at 21:05
  • Yes, that's what I am saying all the time. So there is the potential problem that a developer makes a mistake here and the declaration in META-INF/services may be missing or inconsistent with the one in the module-info.java. That's what I know already. What I am asking for is whether there are additional trouble spots like this which I may have overlooked. – mipa Nov 11 '19 at 23:57