(re-sending with the right domain name)
-------- Forwarded Message --------
Subject: Re: [External] : Different handling of automatic module
version by java and javac
Date: Thu, 27 Aug 2026 08:25:47 +0100
From: Alan Bateman <[email protected]>
To: Rafael Winterhalter <[email protected]>, core-libs-dev
<[email protected]>, [email protected]
On 26/08/2026 22:34, Rafael Winterhalter wrote:
Hei,
I have run into an asymmetry between javac and the runtime in how the
version of an automatic module is treated, and I would like to know
whether
it is intended.
At runtime, ModulePath.deriveModuleDescriptor derives both the name
and the
version of an automatic module from the jar file name. It splits the name
at the first "-" followed by digits, parses the tail with
ModuleDescriptor.Version.parse and, if that succeeds, calls
builder.version(vs). The version is therefore part of the automatic
module's descriptor, and it is visible through Module::getDescriptor
and in
stack traces.
javac derives only the name. Locations.inferModuleName contains a copy of
the same regular expression, under the comment "from
ModulePath.deriveModuleDescriptor", but it uses the match only to truncate
the name and never captures the tail. ModuleSymbol.version is assigned in
just two places, ClassReader (from the module-info.class of the required
module) and Modules (from --module-version), so for an automatic module it
stays null and ClassWriter writes a requires_version_index of 0.
So the version exists at run time but is absent from the compiled
descriptor of the module that requires it. Compiling against a named
module
whose descriptor carries a version does record that version in requires.
Is dropping the derived version in javac intended? If it is, is that
written down anywhere? ModuleDescriptor.Requires.compiledVersion() says
only "the version of the module if recorded at compile-time", which does
not say when it is recorded.
ModuleFinder.of(Path..) [1] is where the derivation of the module name
and version are specified. Would it be possible to send a few examples
where you see the different behavior between compile-time and run-time.
-Alan
[1]
https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/lang/module/ModuleFinder.html#of(java.nio.file.Path...)