RFR: 8362123: ClassLoader Leak via Executors.newSingleThreadExecutor(...)

Viktor Klang vklang at openjdk.org
Fri Sep 26 15:44:04 UTC 2025


On Mon, 14 Jul 2025 15:49:04 GMT, Chris Dennis <duke at openjdk.org> wrote:

> Executors shutdown via `shutdownNow()` should have their cleanables cleaned to prevent a classloader leak. This can happen if a classloader exists that both references the wrapped executor and is referenced by the delegate executor.
> 
> To quote @Martin-Buchholz:
>> BTW: I find Cleaners much harder to use than old finalize, and it looks like I'm not the only one!

test/jdk/java/util/concurrent/Executors/AutoShutdown.java line 74:

> 72: 
> 73:     private static Stream<Arguments> shutdownMethods() {
> 74:         return Stream.<Consumer<ExecutorService>>of(e -> e.shutdown(), e -> e.shutdownNow()).map(Arguments::of);

Suggestion:

        return Stream.<Consumer<ExecutorService>>of(
                e -> e.shutdown(),
                e -> e.shutdownNow()
            ).map(Arguments::of);

test/jdk/java/util/concurrent/Executors/AutoShutdown.java line 126:

> 124:     }
> 125: 
> 126:     @ParameterizedTest

@chrisdennis Would you mind reformat this PR to use less horizontal space?

test/jdk/java/util/concurrent/Executors/AutoShutdown.java line 129:

> 127:     @MethodSource("shutdownMethods")
> 128:     void testShutdownUnlinksCleaner(Consumer<ExecutorService> shutdown) throws Exception {
> 129:         ClassLoader classLoader = Utils.getTestClassPathURLClassLoader(ClassLoader.getPlatformClassLoader());

Suggestion:

        ClassLoader classLoader =
            Utils.getTestClassPathURLClassLoader(ClassLoader.getPlatformClassLoader());

test/jdk/java/util/concurrent/Executors/AutoShutdown.java line 134:

> 132:         Reference<?> reference = new PhantomReference(classLoader, queue);
> 133: 
> 134:         classLoader.loadClass("AutoShutdown$IsolatedClass").getDeclaredMethod("shutdown", Consumer.class).invoke(null, shutdown);

Something like this:
Suggestion:

        classLoader.loadClass("AutoShutdown$IsolatedClass")
                            .getDeclaredMethod("shutdown", Consumer.class)
                            .invoke(null, shutdown);

test/jdk/java/util/concurrent/Executors/AutoShutdown.java line 166:

> 164:     public static class IsolatedClass {
> 165: 
> 166:         private static final ExecutorService executor = Executors.newSingleThreadExecutor(new IsolatedThreadFactory());

Suggestion:

        private static final ExecutorService executor =
            Executors.newSingleThreadExecutor(new IsolatedThreadFactory());

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

PR Review Comment: https://git.openjdk.org/jdk/pull/26296#discussion_r2382785591
PR Review Comment: https://git.openjdk.org/jdk/pull/26296#discussion_r2382776010
PR Review Comment: https://git.openjdk.org/jdk/pull/26296#discussion_r2382782265
PR Review Comment: https://git.openjdk.org/jdk/pull/26296#discussion_r2382777259
PR Review Comment: https://git.openjdk.org/jdk/pull/26296#discussion_r2382781348


More information about the core-libs-dev mailing list