3

I have a jar that works on Java 8.

I would like to create a new jar, that is going to be Multi-Release JAR but empty, just with 'patched' classes in META-INF/versions.

I would like to have a separate jar, so people can include it on Java9, otherwise, they use the default one. Why? Because so many tools are not yet prepared for Java9 MR-Jars.

Would this be possible? Would Java9 MR-Jar override classes from others jars?

Why?

The idea behind Multi-Release jars is that they provide simple patching. In my humble opinion, the way MR jars works is not satisfying.

There are two reasons why I can't make 2 separate Jars:

  1. try to make cross-compile source base that works with Java8 and Java9. You would end up with folders like java, java8 and java9... and then have the build produce two jars, two poms... Yeah, good luck.
  2. Imagine that I even build a library for java9. What about transient dependencies? That would mean that all other libraries that uses mine, would need to have jre8 version that depends on my jre8 version. Just because there is Java9 version!

Here is the story:

My A is a Java library built on Java8 but packaged as Multi-Release Jar which means it contains additional classes for when jar is run on Java9. Additional classes are built separately on JDK9 and I copied them manually (yeah, I know, but it works for now).

Unfortunately, some tools and servers (Jetty) are not aware of MR Jars and this makes them NOT working.

For that reason, I have A-jre8 version of my library, that comes without any extra classes, so servers can use it.

However, if user is using library B that depends on my A, he will still get the MRJar version of A and this will fail again. I want to be able to prevent this somehow. And I can't say to B: hey, could you make B-jre8?

Possible solution

JAR is just about packaging!

  • Allow the separate jar to patch existing jar.

In my case, I would just include A.jar9 and Java would consider A.jar and A.jar9 together as a package. No need for META-INF/versions. Very clean. And, best of all, it would help in situations like above! If run on Java8, the jar9 jar would make no difference; if run on Java9 the jar9 jar would patch the jar with the same name. Simple as that. No transitive dependency hell.

  • Rename classes in META-INF/versions.

Common Oracle, have you ever heard about the classpath scanning? Could you at least rename the classes in versions to e.g. *.class9 so not to be caught by existing classpath scanners.

igr
  • 10,199
  • 13
  • 65
  • 111
  • 2
    Great question. :) If you're willing to create an additional JAR for Java 9, why not simply ship a single one for 9? Wouldn't that be easier? – Nicolai Parlog Feb 02 '18 at 22:31
  • Agreed with @Nicolai, you're anyway creating 2 jars, why not let them be self-sufficient. One for Java8 and less (acc. to the version you support) and another that could be an MR-JAR for Java9 and plus. – Naman Feb 03 '18 at 02:05
  • 1
    Also, to answer the question that the MR-JAR would override classes from other JAR in my understanding shall be **No, it shouldn't be.**. There are a lot of conflicts I could think of like you might try creating the same name jars(same module name), if you duck that, then same package names from different modules(split packages) might be an issue and even when I am not able to see how you would solve both the above, then (thinking out loud) the attribute `Multi-Release` shall be true for your Java9-jar which wouldn't be aware of overriding the classes from another package(from another jar). – Naman Feb 03 '18 at 02:23
  • @Nicolai please see my update why I can't go with the additional JAR for Java9. If you know how to make cross-compilation works in multi-module java project, please let me know. – igr Feb 03 '18 at 05:55
  • @nullpointer I explained why I can't simply have `jre9` version of the library. I really don't see any issue with my proposed situation. There is absolutely no difference if `version` classes are stored in the same jar or in the separate jar. That is just packaging. Yet, having them separate would make a difference for transitive dependencies. – igr Feb 03 '18 at 05:57
  • 1
    How about using `--patch-module =()*` for the Java9 execution while letting those jars remain the same when executed using Java8 (where the MR Jar META-INF/versions/9/ would be ignored anyway). Haven't given this a try yet but theoretically seems possible to patch the module form A8.jar using the A9.jar. – Naman Feb 03 '18 at 07:09

1 Answers1

1

As it is today (Java v9.0.4) - no.

igr
  • 10,199
  • 13
  • 65
  • 111