Skip to content

Conversation

@desruisseaux
Copy link
Contributor

This is a major refactoring of the Maven JAR Plugin for using the standard jar tool instead of Maven Archiver. The standard tool is available through 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 a little bit of special processing for 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, it may be time to abandon our manual creation of a JAR file and rely fully on the jar tool instead.

Benefits

Safer multi-release JAR files

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 is fixed by this pull request. Note that if this verification is not desired, Maven users can disable it by setting the detectMultiReleaseJar plugin option to false.

Main class managed by the jar tool

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.

Options not yet supported by the plugin

This approach allows to add a <jarArgs> configuration option, similar to the <compilerArgs> in the Maven Compiler Plugin. Such option would allow developers to use new tool arguments before they are supported by the plugin.

Examples of options not yet supported by the plugin are --module-version and --hash-modules. Explicit support for those options could be added in a future plugin version, especially since security is becoming more and more a concern.

Easier debugging and toolchain

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 is 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, since the tool can traverse the directory tree itself.

Automatic use of MANIFEST.MF

After this refactor, the plugin automatically uses the META-INF/MANIFEST.MF file found in the classes directory. Before this refactor, the plugin used that file only if explicitly specified in the <manifestFile> archive configuration. The previous policy was discussed in #255. The new policy is a natural consequence of the way that the JAR plugin is reimplemented, and also more useful in the context of multi-module (in Java module sense) projects since each module could contain its own MANIFEST.MF file.

Multi-module projects

The refactoral support multi-module projects, including projects that are both multi-module and multi-release, as discussed in apache/maven-compiler-plugin#998.

Dependencies

This pull request depends on a Maven release which include the following pull requests:

…f the `PathSelector` class of Maven core.

This is for the transition to Maven 4.0.0 API. As a side effect, this change may improve performances because
the new implementation based on `FileVisitor` makes some efforts for avoiding to scan unnecessary directories.
Use `java.util.spi.ToolProvider` API (requires Java 9+).
Files in the `classes` directories are dispatched to the `--manifest` and `--release` options,
which allow additional verifications by the `jar` tool.

Side effects:
* Remove the default `**/package.html` exclude.
* Automatic use of `META-INF/MANIFEST.MF` file found in `classes` directory.
* Automatic Multi-Release always enabled, unless `detectMultiReleaseJar` is set to `false`.
* In a multi-module project, use Java module names as artifact names.
ascheman added a commit to support-and-care/java9-jigsaw-examples that referenced this pull request Dec 19, 2025
Update all m4/pom.xml to use maven-jar-plugin 4.0.0-beta-2-PR508-SNAPSHOT
which provides automatic JAR-per-module creation.

Additional changes:
- Convert example_addExports_manifest/m4/src/modmain from symlink to real
  directory to support MANIFEST.MF with Add-Exports and Main-Class
- Add Maven 4 Migration Notes to example_addExports_manifest/README.adoc
- Document resource handling in README.adoc

Dependencies:
- apache/maven-jar-plugin#508: Automatic JAR-per-module creation
- apache/maven#11505: Module-aware resource copying

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Introduced in the course of support-and-care/maven-support-and-care#137
…project model and the module-info of the JAR file.
Instead of copying the project POM with filtered dependencies,
use the project POM (except dependencies) as the parent POM.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request java Pull requests that update Java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MJAR-289] Support toolchain

1 participant