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...)

Reply via email to