2

I have a Java 8 application I am working on converting to Java 11 and of course with this I am working with the module system for the first time.

I have my application Maven assembly configuration set such that all the JAR files are put in a /lib directory of the bin distribution. The maven-jar-plugin then sets the MANIFEST Class-Path value with all the JAR file names. The application is run with a simple java -jar /lib/application.jar

Moving to Java 11, if I continue to build the bin distribution this way, I'm curious to know how the runtime interprets the MANIFEST Class-Path value? I read through the JAR specs (https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html) and I think I understand it as:

  1. Any modular JAR file (contains module-info.class) will be treated as a non-modular JAR.
  2. Any non-modular JAR file (no module-info.class) will be treated as a non-modular JAR.
  3. Since everything is on the Class-Path, everything is essentially an unnamed module
  4. Since everything is on the Class-Path, the module system is essentially not being used at runtime
  5. Since everything is on the Class-Path, the application should run essentially as if it's still running as Java 8?

If I did want to change this, would I start putting any modular JAR file on the --module-path and keep the other JAR files on the Class-Path?

Michael Remijan
  • 687
  • 7
  • 22

1 Answers1

3

Exactly; Running via -jar all your code is in the unnamed module, while the JDK classes themselves are running on modules, that's why you can see "java.base/" in the stacktraces running with JDK 9+.

So your invocation would have to change from java -jar lib/application.jar to java --module-path lib --module application/your.main.class

You can improve it further by using JLink and/or JPackage, where you can create an executable that already executes your module, like ./bin/application.

Start by adding all jars to the module path and see if the Java doesn't say anything about split packages. So by doing that, it almost certain that your modules will be "automatic modules". So you can experience some ClassNotFoundException.

If that happens, you'll need to --add-module module.

  • 1
    I didn't see anything in the JAR specification of an equivalent Module-Path in the MANIFEST. Correct? – Michael Remijan Mar 29 '21 at 18:43
  • I've been trying JLink, however, from what I've seen, automatic modules cannot be used with JLink. So all the dependences would need to be converted to modules. – Michael Remijan Mar 29 '21 at 18:44
  • Not necessarily. If you use JDeps you can use it even with automatic modules :) https://medium.com/azulsystems/using-jlink-to-build-java-runtimes-for-non-modular-applications-9568c5e70ef4 – Thiago Henrique Hupner Mar 29 '21 at 18:48
  • 1
    And yes, you're correct. You cannot reference other modules via MANIFEST as you could with Class-Path, so there isn't a Module-Path entry. – Thiago Henrique Hupner Mar 31 '21 at 12:23
  • You can run a modular jar file via `java -jar module.jar`, but to do so you need to encode the jar file using the [`jar` command line switch `--main-class`](https://docs.oracle.com/en/java/javase/17/docs/specs/man/jar.html#operation-modifiers-valid-only-in-create-and-update-modes). See the [jenkov module tutorial: setting the main class](https://jenkov.com/tutorials/java/modules.html#setting-the-jar-main-class) for an example. – jewelsea May 25 '22 at 00:02
  • @jewelsea: You can run a modular jar like that, but doing so places the jar on the CLASSPATH, not on the module-path, as this answer states. That is also the information in the article to which you link. When on the classpath the jar does not get many of the benefits of the module system. – Lii Aug 30 '23 at 16:03