You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2026/05/02 10:14:00 UTC

[jira] [Resolved] (GROOVY-11978) RootLoader returns duplicate resource URLs when the same jar appears on parent and child classpaths

     [ https://issues.apache.org/jira/browse/GROOVY-11978?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Paul King resolved GROOVY-11978.
--------------------------------
    Fix Version/s: 6.0.0-alpha-1
       Resolution: Fixed

> RootLoader returns duplicate resource URLs when the same jar appears on parent and child classpaths
> ---------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-11978
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11978
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 6.0.0-alpha-1
>
>
> {\{RootLoader}} (used by the \{{groovy}}, \{{groovyc}}, \{{groovysh}}, \{{groovyConsole}}
> and \{{grape}} launcher scripts) inherits the JVM startup classpath as its parent
> loader. The launcher puts the core groovy jar on \{{-classpath}} to bootstrap
> {\{GroovyStarter}}, and \{{groovy-starter.conf}}'s \{{load !\{groovy.home\}/lib/*.jar}}
> glob then re-adds the same jar to \{{RootLoader}} itself. As a result, the same
> jar appears in two places in the loader hierarchy.
> This causes \{{RootLoader.getResources(name)}} to return two URLs that point to
> the same entry inside the same jar. Anything that walks the enumeration and
> expects providers to be unique trips on this — for example \{{java.util.ServiceLoader}},
> or any \{{ResourceBundle}}/lookup code that aborts on duplicate hits.
> h3. Reproduction
> Run any launcher that hits resource enumeration on the core jar; \{{groovyConsole}}
> fails on startup with:
> {noformat}
> java.util.MissingResourceException: Can't find bundle for base name groovy.console.ui.Console, locale en_AU
>     at java.base/java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2045)
>     ...
>     at org.codehaus.groovy.tools.shell.util.MessageSource.createBundles(MessageSource.java:78)
>     at org.codehaus.groovy.tools.shell.util.MessageSource.getMessage(MessageSource.java:99)
>     at groovy.console.ui.Console.main(Console.groovy:336)
> {noformat}
> h3. Fix
> Override \{{RootLoader.getResources(String)}} so URLs whose canonical jar file
> has already been seen are collapsed. Walks \{{findResources}} first then the
> parent chain, matching the existing child-first behaviour of \{{getResource}}.
> Non-jar URLs (directories, custom protocols) are passed through unchanged;
> canonical-file matching means symlinked jars also dedup correctly.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)