possible bug in jdeps as ToolProvider

Mandy Chung mandy.chung at oracle.com
Tue Dec 21 20:59:14 UTC 2021


Your contribution is welcome but this may not be a starter bug.   The 
proper fix is to change it to per-jdeps-invocation map but not clearing 
the map.  I haven't put time to think through the best way to fix it 
cleanly.

Mandy

On 12/21/21 12:38 PM, Raymond Augé wrote:
> Mandy, would you accept a PR for this?
>
> (I would have to start the process to get an OCA.)
>
> Ray
>
> On Tue, Dec 21, 2021 at 3:26 PM Mandy Chung <mandy.chung at oracle.com> 
> wrote:
>
>     The issue has existed since the initial support of multi-release
>     JARs (JDK-8153654
>     <https://bugs.openjdk.java.net/browse/JDK-8153654>) since JDK 9.
>
>     Mandy
>
>     On 12/20/21 7:38 PM, Raymond Augé wrote:
>>     I should add that I have reproduced this issue on Java 11 and 17.
>>     The ticket only indicates Java 18 but that in not accurate.
>>
>>     On Mon., Dec. 20, 2021, 1:33 p.m. Raymond Augé,
>>     <raymond.auge at liferay.com> wrote:
>>
>>         Thank you Mandy.
>>
>>         On Mon., Dec. 20, 2021, 1:19 p.m. Mandy Chung,
>>         <mandy.chung at oracle.com> wrote:
>>
>>             Yes this bug is known and tracked by JDK-8277681.  The
>>             proper solution should make each JdepsTask to maintain
>>             its own map of multi-versioned entries rather than a
>>             global nameToVersion map for the running VM as described in
>>             JDK-8277681.
>>
>>             Mandy
>>
>>             On 12/18/21 7:47 PM, Raymond Augé wrote:
>>>             Hello everyone,
>>>
>>>             At Alan's request [3] I'm posting this here. Alan mentions this is likely a
>>>             manifestation of JDK-8277681 [4]. From the description I would agree.
>>>
>>>             Here is a copy of the original message for posterity.
>>>             -------------------
>>>             I believe I have found a small bug in jdeps tool when used as ToolProvider.
>>>
>>>             I am invoking the jdeps impl via the ToolProvider API as follows (this code
>>>             is also available here [2]):
>>>
>>>                try (final StringWriter stdout = new StringWriter();
>>>                    final StringWriter stderr = new StringWriter();
>>>                    final PrintWriter pwout = new PrintWriter(stdout);
>>>                    final PrintWriter pwerr = new PrintWriter(stderr)) {
>>>
>>>                  return (ToolProvider.findFirst("jdeps").orElseThrow().run(pwout, pwerr,
>>>             args) == 0) ?
>>>                    stdout.toString() :
>>>                    "Error: ".concat(stderr.toString());
>>>                }
>>>                catch (Throwable t) {
>>>                  t.printStackTrace();
>>>                  return "Error: " + t.getMessage();
>>>                }
>>>
>>>             However repeat invocations result in the following exception:
>>>
>>>             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)
>>>                [snip]
>>>             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)
>>>             ... 24 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(FutureTask.java:264)
>>>             at
>>>             java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
>>>             at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
>>>             at
>>>             java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
>>>             at
>>>             java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
>>>             at java.base/java.lang.Thread.run(Thread.java:829)
>>>
>>>             In order to get around the error I do the following:
>>>
>>>             public static final Field field;
>>>             public static final Map<?,?> map;
>>>
>>>             static {
>>>                try {
>>>                  Class<?> clazz = Class.forName("com.sun.tools.jdeps.VersionHelper");
>>>                  field = clazz.getDeclaredField("nameToVersion");
>>>                  field.setAccessible(true);
>>>                  map = (Map<?,?>)field.get(null);
>>>                }
>>>                catch (ReflectiveOperationException e) {
>>>                  throw new RuntimeException(e);
>>>                }
>>>             }
>>>
>>>             and tack a finally to the end of the try above:
>>>
>>>             finally {
>>>                map.clear();
>>>             }
>>>
>>>             Now, additionally to be able to do that, I need to add an `--add-opens`:
>>>
>>>             --add-opens jdk.jdeps/com.sun.tools.jdeps=ALL-UNNAMED
>>>
>>>             I believe the solution is to clear the map in [1] when jdeps finishes.
>>>
>>>             Finally, I would send a PR myself except I do not (yet) have an OCA and the
>>>             solution seems simple enough if someone can confirm that this is indeed a
>>>             bug.
>>>
>>>             Ray
>>>
>>>             [1]
>>>             https://github.com/openjdk/jdk/blob/master/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java  <https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java__;!!ACWV5N9M2RV99hQ!ep-GUts1P9CJOX1wA0Rd6QP3kuSFocnoeMKvPETK7DYwDQJqLJcxumOCMg4gPsG-7A$>
>>>             [2]https://gist.github.com/rotty3000/d9feec79a66f14c2360fee9b9a1b2852  <https://urldefense.com/v3/__https://gist.github.com/rotty3000/d9feec79a66f14c2360fee9b9a1b2852__;!!ACWV5N9M2RV99hQ!ep-GUts1P9CJOX1wA0Rd6QP3kuSFocnoeMKvPETK7DYwDQJqLJcxumOCMg69o94Tag$>
>>>             [3]
>>>             https://mail.openjdk.java.net/pipermail/jdk-dev/2021-December/006291.html
>>>             [4]https://bugs.openjdk.java.net/browse/JDK-8277681
>>
>
>
>
> -- 
> *Raymond Augé* (@rotty3000)
> Senior Software Architect *Liferay, Inc.* (@Liferay)
> OSGi Fellow, Java Champion


More information about the core-libs-dev mailing list