Search code examples
jarjava-9multi-release-jar

Can MR-Jars overwrite classes from other jars?


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.


Solution

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