0

A lot of Java projects shade their dependencies. I believe the main reason is illustrated by the answer on this SO question (What is the maven-shade-plugin used for, and why would you want to relocate Java packages?). To summarize:

  • Library Foo has dependency Bar:1.0 and can't upgrade to Bar:2.0
  • Qux depends on library Foo but also depends on Bar:2.0
  • Without shading, Bar:1.0 and Bar:2.0 would conflict, so library Foo uses a shaded version of Bar and depends on this shaded version to not negatively impact downstream projects that wish to use a different version of Bar.

My question is does Java Modules (JPMS/Jigsaw) also solve this problem without the need for shading? I understand that today, most Java projects aren't using JPMS, but in the scenario that Qux/Foo/Bar were all fully using JPMS modules, could they avoid conflicts without Foo needing to use a shaded version of Bar?

clay
  • 18,138
  • 28
  • 107
  • 192
  • 1
    Yes and no. You’d need a special class loader setup, but that’s not so different to the situation before the JPMS; you could have solved the problem with a special class loader setup instead of shading at any time. – Holger Jun 12 '23 at 14:55

1 Answers1

1

No

Jigsaw does not support versioning at all.

The only thing that Jigsaw does in this respect is to prohibit having more than one module exporting the same package. If that happens you will get an error message like this:

Error occurred during initialization of boot layer
java.lang.LayerInstantiationException: Package org.example in both module somejar.v2 and module somejar.v1

In other words: It tells you when you need to start shading. Unfortunately the maven-shade-plugin does not support Jigsaw yet: https://issues.apache.org/jira/browse/MSHADE-234

One can create runtime images with jlink, but they cannot be put on the module path of another Java executable (They are also much bigger and platform dependent BTW).

There is also no concept of self-contained modules (jar with dependencies) in Jigsaw.

  • Thank you for the reply. You sound very knowledgeable. However, the Log4j 3.0 alpha release notes suggest otherwise when using ServiceLoaders: "All plugins constructed using Log4j 3.x are now located using Java’s ServiceLoader. This avoids many of the problems users had packaging plugins in "shaded" jars". https://lists.apache.org/thread/rhkjrfy1d0oddcfmzqwnodflxqhq2d3l – clay Jul 09 '23 at 00:25
  • ServiceLoader is not something new to Jigsaw. This exists since Java 6: https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html. See also: https://dzone.com/articles/java-9-module-services. I tested it: Even if you use the ServiceLoader mechanism, when having a package twice in two Jigsaw modules you will get the error I mentioned in the answer. Test it yourself! I think what they meant by this release note is that they now have a standardized mechanism for plugins which makes it easier to put it into shaded jars. Previously their plugin mechanism was proprietary to Log4j. – nineninesevenfour Jul 14 '23 at 06:57
  • TBH, Java 9 modules make the programmer's life just harder. The only pro for me is having more control of visibility of packages. The list of cons is much longer. And it breaks so many tools around. In their concept they totally ignored real-world use cases. No support for versioning and no extended visibility for testing. It makes reflection pointless, as by default I can only reflect things in my own module. My personal advice it to stay away from it as long as you can. – nineninesevenfour Jul 14 '23 at 07:26