RFR: 8338445: jdk.internal.loader.URLClassPath may leak JarFile instance when dealing with unexpected Class-Path entry in manifest

Alan Bateman alanb at openjdk.org
Sun Aug 25 15:17:04 UTC 2024


On Fri, 23 Aug 2024 10:45:49 GMT, Jaikiran Pai <jpai at openjdk.org> wrote:

> Can I please get a review of this change which proposes to fix the issue noted in https://bugs.openjdk.org/browse/JDK-8338445?
> 
> The JDK internal class `jdk.internal.loader.URLClassPath` is used by classloader implementations in the JDK (for example by the `java.net.URLClassLoader` and the `jdk.internal.loader.ClassLoaders$AppClassLoader`). The implementation in `URLClassPath` constructs internal `Loader`s for each URL that is in the classpath of that instance. `Loader` implementations hold on to underlying resources from which the classpath resources are served by the `URLClassPath`.
> 
> When constructing a `Loader`, the `URLClassPath` allows the loader implementation to parse a local classpath for that specific `Loader`. For example, the `JarLoader` (an internal class of the JDK) will parse `Class-Path` attribute in the jar file's manifest to construct additional URLs that will be included in the classpath through which resources will be served by `URLClassPath`. While parsing the local classpath, if the `Loader` instance runs into any `IOException` or a `SecurityException`, the `URLClassPath` will ignore that specific instance of the `Loader` and will not hold on to it as a classpath element.
> 
> As noted earlier, `Loader` instances may hold onto underlying resources. When the `URLClassPath` ignores such `Loader`(s) and doesn't call `close()` on them, then that results in potential resource leaks. The linked JBS issue demonstrates a case where the `JarFile` held by the `JarLoader` doesn't get closed (until GC garbage collects the `JarLoader` and thus the `JarFile`), when the `URLClassPath` ignores that `JarLoader` due to an `IOException` when the `JarLoader` is parsing the `Class-Path` value from the jar's manifest.
> 
> The commit in this PR addresses the issue by calling `close()` on such `Loader`s that get rejected by the `URLClassPath` when either an `IOException` or a `SecurityException` gets thrown when constructing the `Loader` or parsing the local classpath.
> 
> A new jtreg test has been introduced which consistently reproduces this issue (on Windows) and verifies the fix. Additionally tier1, tier2 and tier3 testing has completed with this change without any failures.

The change looks okay, I suspect the issue with handling malformed Class-Path values has been there for 20+ years but hasn't come up. For the bug report then it would be interesting to know if there is a plugin in the eco system that is creating the bad values or whether it's just a one-off.

src/java.base/share/classes/jdk/internal/loader/URLClassPath.java line 447:

> 445:                 loader = getLoader(url);
> 446:                 // If the loader defines a local class path then construct
> 447:                 // and add the URLs as the next URLs to be opened.

The change to URLClassLoad looks okay although I think the original comment was a bit clearer, no need to insert "then construct" here as this is just getting the class path URLs.

src/java.base/share/classes/jdk/internal/loader/URLClassPath.java line 453:

> 451:                 if (DEBUG) {
> 452:                     System.err.println("Failed to construct a loader or construct its" +
> 453:                             " local classpath for " + url + ", cause:" + e);

At some point we should probably get rid of the DEBUG stuff, it looks like it was left over from early JDK releases.

src/java.base/share/classes/jdk/internal/loader/URLClassPath.java line 482:

> 480: 
> 481:     // closes the given loader and ignores any IOException that may occur during close
> 482:     private static void closeLoaderIgnoreEx(final Loader loader) {

closeQuietly(Loader loader) would work too.

test/jdk/java/net/URLClassLoader/JarLoaderCloseTest.java line 78:

> 76: 
> 77:     /*
> 78:      * Creates a jar with a manifest which has a Class-Path entry value with malformed URLs.

I think you mean a "a JAR file" rather than "jar" here. Same nit in  testParsableClassPathEntry.

-------------

PR Review: https://git.openjdk.org/jdk/pull/20691#pullrequestreview-2259319752
PR Review Comment: https://git.openjdk.org/jdk/pull/20691#discussion_r1730378354
PR Review Comment: https://git.openjdk.org/jdk/pull/20691#discussion_r1730378430
PR Review Comment: https://git.openjdk.org/jdk/pull/20691#discussion_r1730378528
PR Review Comment: https://git.openjdk.org/jdk/pull/20691#discussion_r1730379053


More information about the core-libs-dev mailing list