Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

read of JPMS multi-release jars fails if a newer version than supported is present #32

Closed
richard-melvin opened this issue Aug 19, 2020 · 8 comments

Comments

@richard-melvin
Copy link

JEP 238 multi-release jars are intended to support new JDK releases in a backwards compatible way.

However, if you create a trivial JPMS project with a dependency on a multi-release jar that contains a newer version than the JDK used to run maven, you risk getting a fatal exception from the maven compiler plugin that blocks compilation:

Caused by: java.lang.module.InvalidModuleDescriptorException: Unsupported major.minor version 56.0
    at jdk.internal.module.ModuleInfo.invalidModuleDescriptor (ModuleInfo.java:1091)
    at jdk.internal.module.ModuleInfo.doRead (ModuleInfo.java:195)
    at jdk.internal.module.ModuleInfo.read (ModuleInfo.java:131)
    at java.lang.module.ModuleDescriptor.read (ModuleDescriptor.java:2487)
    at org.codehaus.plexus.languages.java.jpms.BinaryModuleInfoParser.parse (BinaryModuleInfoParser.java:35)
    at org.codehaus.plexus.languages.java.jpms.AbstractBinaryModuleInfoParser.getModuleDescriptor (AbstractBinaryModuleInfoParser.java:84)
    at org.codehaus.plexus.languages.java.jpms.LocationManager.resolvePaths (LocationManager.java:127)
    at org.apache.maven.plugin.compiler.CompilerMojo.preparePaths (CompilerMojo.java:238)

This is because AbstractBinaryModuleInfoParser::getModuleDescriptor iterates through all module-info.class files found in a jar in an unordered way, and simply takes the first one found.

For example, a trivial project with dependency:

			<dependency>
				<!--JSR 385 unit service -->
				<groupId>tech.units</groupId>
				<artifactId>indriya</artifactId>
				<version>2.0.4</version>
				<exclusions>
					<exclusion>
						<groupId>javax.inject</groupId>
						<artifactId>javax.inject</artifactId>
					</exclusion>
				</exclusions>
			</dependency>

compiled on the platform below gives that error

mvn --version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.8, vendor: AdoptOpenJDK, runtime: /usr/lib/jvm/adoptopenjdk-11-hotspot-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-42-generic", arch: "amd64", family: "unix"
java --version
openjdk 11.0.8 2020-07-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.8+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.8+10, mixed mode)

This is because tech/units/indriya/2.0.4 (as available on maven central) has:

 file  META-INF/versions/*/module-info.class
META-INF/versions/12/module-info.class: compiled Java class data, version 56.0
META-INF/versions/14/module-info.class: compiled Java class data, version 58.0
META-INF/versions/9/module-info.class:  compiled Java class data, version 53.0

And so in JDK 11, it tries to read the JDK 12 version first, which throws the above exception.

Refs:

https://openjdk.java.net/jeps/238

@rfscholte
Copy link
Member

I can confirm that the code now looks for the first module-info.class entry and doesn't verify the version as it should. Needs to be fixed in https://github.com/codehaus-plexus/plexus-languages/blob/master/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AbstractBinaryModuleInfoParser.java

@rfscholte
Copy link
Member

Fixed with 020a7f2

@soc
Copy link

soc commented Jul 6, 2021

Hi Robert, I'm experiencing this issue – is there a way to benefit from this fix already?

I added

            <dependency>
              <groupId>org.codehaus.plexus</groupId>
              <artifactId>plexus-languages</artifactId>
              <version>1.0.7</version>
              <type>pom</type>
            </dependency>
            <dependency>
              <groupId>org.codehaus.plexus</groupId>
              <artifactId>plexus-java</artifactId>
              <version>1.0.7</version>
            </dependency>

to maven-compiler-plugin's (3.8.1) dependencies, but I receive the following error message:

A required class was missing while executing org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile:
 org/codehaus/plexus/languages/java/jpms/ResolvePathsResult$ModuleNameSource
-----------------------------------------------------
realm =    plugin>org.apache.maven.plugins:maven-compiler-plugin:3.8.1
strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
urls[0] = file:/home/soc/.m2/repository/org/apache/maven/plugins/maven-compiler-plugin/3.8.1/maven-compiler-plugin-3.8.1.jar
urls[1] = file:/home/soc/.m2/repository/org/ow2/asm/asm/9.2/asm-9.2.jar
urls[2] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-component-annotations/2.1.0/plexus-component-annotations-2.1.0.jar
urls[3] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-languages/1.0.7/plexus-languages-1.0.7.pom
urls[4] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-java/1.0.7/plexus-java-1.0.7.jar
urls[5] = file:/home/soc/.m2/repository/com/thoughtworks/qdox/qdox/2.0-M9/qdox-2.0-M9.jar
urls[6] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-compiler-api/2.8.8/plexus-compiler-api-2.8.8.jar
urls[7] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-utils/3.3.0/plexus-utils-3.3.0.jar
urls[8] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-compiler-manager/2.8.8/plexus-compiler-manager-2.8.8.jar
urls[9] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-compiler-javac/2.8.8/plexus-compiler-javac-2.8.8.jar
urls[10] = file:/home/soc/.m2/repository/org/apache/maven/shared/maven-shared-utils/3.3.4/maven-shared-utils-3.3.4.jar
urls[11] = file:/home/soc/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar
urls[12] = file:/home/soc/.m2/repository/org/sonatype/sisu/sisu-inject-bean/1.4.2/sisu-inject-bean-1.4.2.jar
urls[13] = file:/home/soc/.m2/repository/org/sonatype/sisu/sisu-guice/2.1.7/sisu-guice-2.1.7-noaop.jar
urls[14] = file:/home/soc/.m2/repository/org/sonatype/aether/aether-util/1.7/aether-util-1.7.jar
urls[15] = file:/home/soc/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.jar
urls[16] = file:/home/soc/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar
urls[17] = file:/home/soc/.m2/repository/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar
urls[18] = file:/home/soc/.m2/repository/org/apache/maven/shared/maven-shared-incremental/1.1/maven-shared-incremental-1.1.jar

...
Caused by: java.lang.ClassNotFoundException: org.codehaus.plexus.languages.java.jpms.ResolvePathsResult$ModuleNameSource
    at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass (SelfFirstStrategy.java:50)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass (ClassRealm.java:271)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass (ClassRealm.java:247)
    at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass (ClassRealm.java:239)
    at org.apache.maven.plugin.compiler.CompilerMojo.detectFilenameBasedAutomodules (CompilerMojo.java:315)
    at org.apache.maven.plugin.compiler.CompilerMojo.preparePaths (CompilerMojo.java:253)
    at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute (AbstractCompilerMojo.java:792)
    at org.apache.maven.plugin.compiler.CompilerMojo.execute (CompilerMojo.java:187)

@soc
Copy link

soc commented Jul 6, 2021

This is curious, the move of the enum to a top-level element happened in 2018: 01d3f9f#diff-832e0b5d7b97ff4be7e6e22b2751e50fe5670dfe219e438617bb6dc194d9280c

So there seems to be some other dependency that hasn't been updated. Perhaps it was also broken before, but no referring class was initialized on the MR-less codepath, so it never showed up as an exception.

I explicitly specified the versions of

  • asm:9.2
  • plexus-component-annotations:2.1.0
  • plexus-languages:1.0.7
  • plexus-java:1.0.7
  • plexus-compiler-api:2.8.8
  • plexus-compiler-manager:2.8.8
  • plexus-compiler-javac:2.8.8

to no avail.

@rfscholte
Copy link
Member

Maven Compiler Plugin 3.8.1 is using plexus-java-0.9.10, see http://maven.apache.org/plugins/maven-compiler-plugin/dependencies.html
IIRC the plugin already has a higher version of plexus-java including the required code changes on the master branch, but it hasn't been released yet.

@soc
Copy link

soc commented Jul 7, 2021

@rfscholte Thanks!

Maven Compiler Plugin 3.8.1 is using plexus-java-0.9.10

Yes, I hoped that I would be able to upgrade the plexus-java dependency on its own, but as I figured out they weren't binary compatible.

it hasn't been released yet

Is there any idea when the next maven-compiler-plugin release is planned to ship?

@rfscholte
Copy link
Member

I think everybody will look at me to do the release, but any Maven committer can do it. I first have other topics to work on, but we should do one before Java 17. I'd suggest to ask for a release in September.

@soc
Copy link

soc commented Jul 7, 2021

Thanks for the info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants