When building an application jar with Maven Shade, is it safe to exclude all META-INF/versions directories/files?

Tags: ,



I believe the versions folders are there to support multiple Java versions. We always build for a very specific version (at this time 11). Is there a danger to excluding those directories/files when creating our single application jar? ex.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
    <transformers>
        <transformer
            implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>${start-class}</mainClass>
            <manifestEntries>
                <Class-Path>./</Class-Path>
                <Implementation-Version>${ourSoftware.revision}</Implementation-Version>
            </manifestEntries>
        </transformer>
    </transformers>
    <filters>
        <filter>
            <artifact>*:*</artifact>

            <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>

                <exclude>META-INF/versions/**</exclude> <!-- IS THIS SAFE? -->
            </excludes>
        </filter>
    </filters>
    <finalName>${project.artifactId}App</finalName>
</configuration>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
    </execution>
</executions>

Thanks!

Answer

Yes, these versions folders are for the support of Multi-Release Jar Files (see JEPS 238).

It seems safe to me provided that you explicitely set the multi-release attribute to false in the MANIFEST.MF file.

Here is how it works:

In a JDK that does not support MRJARs, only the classes and resources in the root directory will be visible, and the two packagings will be indistinguishable. In a JDK that does support MRJARs, the directories corresponding to any later Java platform release would be ignored; it would search for classes and resources first in the Java platform-specific directory corresponding to the currently-running major Java platform release version, then search those for lower versions, and finally the JAR root. On a Java 9 JDK, it would be as if there were a JAR-specific class path containing first the version 9 files, and then the JAR root; on a Java 8 JDK, this class path would contain only the JAR root. (Ref: JEPS 238)

This version based packaging mechanism selectively ignores non – relevant versions folders even if there is content inside. desabling the mechanism should resolve to ignoring all versions folders if they are present and falling back exactly to the behavior that existed before JEPS 238 if they are not present.



Source: stackoverflow