possible bug in jdeps as ToolProvider
Raymond Augé
raymond.auge at liferay.com
Tue Dec 21 03:38:46 UTC 2021
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
>> [2] https://gist.github.com/rotty3000/d9feec79a66f14c2360fee9b9a1b2852
>> [3]https://mail.openjdk.java.net/pipermail/jdk-dev/2021-December/006291.html
>> [4] https://bugs.openjdk.java.net/browse/JDK-8277681
>>
>>
>>
More information about the core-libs-dev
mailing list