Skip to content

Migrate from Maven Archiver to standard "jar" tool #495

@desruisseaux

Description

@desruisseaux

New feature, improvement proposal

This is a description of a work being done as part of Full Java Module Support effort. If the principle is accepted, a pull request will be submitted later. This issue is for collecting feedbacks in the meantime.

This work is a refactoring of the Maven JAR plugin for using the standard jar tool instead of Maven Archiver. It can be done by using the java.util.spi.ToolProvider interface, which was introduced in Java 9. Since Maven 4 upgraded its requirement from Java 8 to Java 17, the use of that interface is no longer problematic.

Rational

In early Java days, the jar tool was equivalent to a zip command with a different syntax and with the addition of a special handling of the META-INF/MANIFEST.MF file. Because of this quasi-equivalence, it was not difficult to create JAR files ourselves using any library capable to write ZIP files. This is what Maven Archiver does, together with supporting other archive formats. But today, the jar tool became more sophisticated. It now includes options for verifying the consistency of multi-release JAR files, options for updating module-info.class, provides security features specific to Java, etc.. This evolution can be seen in the "Modular JAR files" section of the Maven Plugin documentation, which states that the plugin uses the jar tool for updating the JAR file in a way that the Maven Archiver can't do easily. Therefore, since Maven 4 requires Java 17 and since that Java version gives us an easy access to the jar tool through the java.util.spi.ToolProvider interface (available since Java 9), it may be time to abandon our manual creation of a JAR file and rely fully on the jar tool instead.

Benefits

In a multi-release JAR file, blindingly storing the content of META-INF/versions/ directories as if they were ordinary resources is not equivalent to using the jar --release option. The difference is that in the latter case, the jar tool performs some consistency checks. This issue was independently reported by user in #484, which would be fixed by this proposal. Note that if this verification is not desired, Maven users can disable it by setting the detectMultiReleaseJar plugin option to false.

In a modular JAR file, it is no longer sufficient to declare the main class in the Main-Class entry of the MANIFEST.MF file. The main class needs to be specified by the --main-class option of the jar tool, which will update module-info.class. For compatibility reason the Maven JAR plugin gets the option value from that manifest entry, but internally the use of the jar tool is mandatory.

Other options such as --module-version and --hash-modules which are not yet used in the current plugin will become used in a future version, especially since security is becoming more and more a concern.

This approach makes easy to generate a target/jar.args file when the build fails or when Maven is run in verbose mode. This is similar to the compiler plugin generating a target/javac.args file. This file allows the user to test easily on the command-line, which makes debugging faster. Likewise, the options can also be passed to another tool, which makes easier to resolve #439 as well.

Behavioral changes

The plugin behaviour after the proposed refactoring would be different than version 3 in the following aspects:

Removal of default **/package.html excludes

The current plugin version uses an undocumented **/package.html default excludes. This default seems to exist since the initial revision in March 2004, but I saw no explanation for this oddity. This default is not mentioned in the documentation. The removal of this oddity is necessary for allowing the proposed new plugin implementation to specify only some root directories to the jar tool, which can traverse the directory tree itself.

Prototype

If accepted, the pull request would be created from this clone after all integration tests pass (this is not yet the case at the time of writing this issue).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions