JDK-8277165 : jdeps --multi-release --print-module-deps fails if module-info.class in different versioned directories
  • Type: Bug
  • Component: tools
  • Affected Version: 18
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-11-16
  • Updated: 2022-03-17
  • Resolved: 2021-11-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 18
17.0.4-oracleFixed 18 b26Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
To reproduce, create 2 module source folders with a simple module-info.java class:

    ├───mod.bar
    │       module-info.java
    │
    ├───mod.baz
    │       module-info.java

Compile and create 2 jar files, each with the module-info class under a separate version:

    $ javac --module-source-path . -d out -m mod.bar
    $ javac --module-source-path . -d out -m mod.baz
    $ jar --create --file mod-bar.jar --release 11 -C 'out/mod.bar' module-info.class
    $ jar --create --file mod-baz.jar --release 12 -C 'out/mod.baz' module-info.class

Then run jdeps over both jars with the higher of the 2 release versions passed to multi-release:

    jdeps --multi-release 12 --print-module-deps mod-bar.jar mod-baz.jar

This will sometimes produce an exception (just spam it in the console a few times, and you should see it):

Exception in thread "main" java.lang.Error: java.util.concurrent.ExecutionException: com.sun.tools.jdeps.MultiReleaseException
	at jdk.jdeps/com.sun.tools.jdeps.DependencyFinder.waitForTasksCompleted(DependencyFinder.java:271)
	at jdk.jdeps/com.sun.tools.jdeps.DependencyFinder.parse(DependencyFinder.java:133)
	at jdk.jdeps/com.sun.tools.jdeps.DepsAnalyzer.run(DepsAnalyzer.java:129)
	at jdk.jdeps/com.sun.tools.jdeps.ModuleExportsAnalyzer.run(ModuleExportsAnalyzer.java:74)
	at jdk.jdeps/com.sun.tools.jdeps.JdepsTask$ListModuleDeps.run(JdepsTask.java:1047)
	at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:574)
	at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
	at jdk.jdeps/com.sun.tools.jdeps.Main.run(Main.java:64)
	at jdk.jdeps/com.sun.tools.jdeps.Main$JDepsToolProvider.run(Main.java:73)
	at java.base/java.util.spi.ToolProvider.run(ToolProvider.java:138)
	at main.JDepsMultiRelease.main(JDepsMultiRelease.java:12)
Caused by: java.util.concurrent.ExecutionException: com.sun.tools.jdeps.MultiReleaseException
	at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
	at jdk.jdeps/com.sun.tools.jdeps.DependencyFinder.waitForTasksCompleted(DependencyFinder.java:267)
	... 10 more
Caused by: com.sun.tools.jdeps.MultiReleaseException
	at jdk.jdeps/com.sun.tools.jdeps.VersionHelper.add(VersionHelper.java:62)
	at jdk.jdeps/com.sun.tools.jdeps.ClassFileReader$JarFileReader.readClassFile(ClassFileReader.java:360)
	at jdk.jdeps/com.sun.tools.jdeps.ClassFileReader$JarFileIterator.hasNext(ClassFileReader.java:402)
	at jdk.jdeps/com.sun.tools.jdeps.DependencyFinder.lambda$parse$5(DependencyFinder.java:179)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

 The reason that an exception is only reported _sometimes_ is the result of a data-race in jdep's VersionHelper. See: https://bugs.openjdk.java.net/browse/JDK-8277166 (applying the fix I suggested in the comments there makes this 100% reproducible).

2 jars defining a module-info.class in a different versioned directory is valid as far as I know (it's not a case of split packages). So, an exception should not be thrown in this case I think.
    
Comments
A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk17u-dev/pull/256 Date: 2022-03-15 09:34:18 +0000
15-03-2022

Fix request [17u] I backport this for parity with 17.0.4-oracle. Clean backport. Small change, low risk. Fix requested by several parties. SAP nightly testing passes.
15-03-2022

Backport Fix Request to jdk17u: This fixes jdeps --print-module-deps and relevant options in analyzing the module dependences among multi-release JARs that contain module-info.class in its versioned entry. jdeps intends to detect if there are multiple versions of the same class present and reports as an error. It's a bug in jdeps that should skip module-info.class for such checking. The fix is straight-forward and simply skip module-info.class for multiple versions check. This patch also includes trivial fix for JDK-8277166 and JDK-8277123 to fix the data race in multiple versions checking as well as proper reporting of the multiple versions error message. The backport is direct import of the commit openjdk/jdk/7e54d065.
30-11-2021

Changeset: 7e54d065 Author: Mandy Chung <mchung@openjdk.org> Date: 2021-11-26 01:55:58 +0000 URL: https://git.openjdk.java.net/jdk/commit/7e54d065a17f1277adf1b8561fadb8a480bc6bed
26-11-2021

module-info.class should be excluded when checking if there are multiple versions of the same class file.
23-11-2021