RFR: 6957241: ClassLoader.getResources() returns only 1 instance when using jar indexing
wxiang
github.com+53162078+shiyuexw at openjdk.java.net
Tue Sep 7 03:39:36 UTC 2021
On Tue, 31 Aug 2021 12:11:46 GMT, wxiang <github.com+53162078+shiyuexw at openjdk.org> wrote:
> Using jarIndex for Hibench, there is an unexpected behavior with the exception "Exception in thread "main" org.apache.hadoop.fs.UnsupportedFileSystemException: No FileSystem for scheme "hdfs"".
>
> After investigating it, it is related to the usage of ServiceLoader with JarIndex.
> The below stack shows the issue with JDK11:
>
> getResource:1016, URLClassPath$JarLoader (jdk.internal.loader)
> getResource:937, URLClassPath$JarLoader (jdk.internal.loader)
> findResource:912, URLClassPath$JarLoader (jdk.internal.loader)
> next:341, URLClassPath$1 (jdk.internal.loader)
> hasMoreElements:351, URLClassPath$1 (jdk.internal.loader)
> hasNext:355, BuiltinClassLoader$1 (jdk.internal.loader)
> hasMoreElements:363, BuiltinClassLoader$1 (jdk.internal.loader)
> next:3032, CompoundEnumeration (java.lang)
> hasMoreElements:3041, CompoundEnumeration (java.lang)
> nextProviderClass:1203, ServiceLoader$LazyClassPathLookupIterator (java.util)
> hasNextService:1221, ServiceLoader$LazyClassPathLookupIterator (java.util)
> hasNext:1265, ServiceLoader$LazyClassPathLookupIterator (java.util)
> hasNext:1300, ServiceLoader$2 (java.util)
> hasNext:1385, ServiceLoader$3 (java.util)
>
> The below API tries to get all the resources with the same name.
>
> public Enumeration<URL> findResources(final String name,
> final boolean check)
> ```
> After using JarIndex, URLClassPath.findResources only returns 1 URL.
> It is the same as the description in JDK-6957241.
>
> The issue still exists in JDK18.
>
> Root cause:
>
> public Enumeration<URL> findResources(final String name,
> final boolean check) {
> return new Enumeration<>() {
> private int index = 0;
> private URL url = null;
>
> private boolean next() {
> if (url != null) {
> return true;
> } else {
> Loader loader;
> while ((loader = getLoader(index++)) != null) {
> url = loader.findResource(name, check);
> if (url != null) {
> return true;
> }
> }
> return false;
> }
> }
> ...
> };
> }
>
> With the JarIndex, there is only one loader which is corresponding to the jar with the index due to the implementation in JarLoader.getResource(final String name, boolean check, Set<String> visited).
>
> Loaders corresponding to other jar packages will not appear in this while.
> So it only returns 1 instance.
>
> To solve the issue, I change the implementation "private boolean next()".
> If the loader has index, traverse the index and get all the resource from the loader.
I created a new JBS https://bugs.openjdk.java.net/browse/JDK-8273401, and PR: https://github.com/openjdk/jdk/pull/5383.
The PR is to remove the JarIndex support in URLClassPath and move JarIndex into the jdk.jartool module.
-------------
PR: https://git.openjdk.java.net/jdk/pull/5316
More information about the core-libs-dev
mailing list