Apologies, that description is pretty lousy. A more explicit description of the leak (the one in my test in https://github.com/openjdk/jdk/pull/26296) would be: A class loaded by classloader 'C' statically references an Executor created via newSingleThreadExecutor(threadFactory). The ThreadFactory is an instance of a class also loaded by 'C'. This executor is then shutdown via shutdownNow(). The resulting structure will pin the classloader 'C' in memory.
Chris On Tue, 15 Jul 2025 at 06:50, Alan Bateman <alan.bate...@oracle.com> wrote: > On 11/07/2025 15:42, Chris Dennis wrote: > > Hi All, > > > > I believe I've identified a bug in > > Executors.AutoShutdownDelegatedExecutorService that can trigger a > > classloader leak even in the presence of "correct" Executor > > lifecycling. AutoShutdownDelegatedExecutorService only unlinks the > > PhantomReference used for cleanup handling when it is shutdown via the > > shutdown() method. If an Executor wrapped in this way is instead > > shutdown using the shutdownNow() method and it references a > > classloader via an injected attribute: ThreadFactory, AbortPolicy, > > etc. then the cleanup action will reference the classloader, and the > > classloader will remain strongly referenced. Adding an additional > > override as shown in the attached patch is sufficient to fix the leak > > in my testing. > > > It would be useful if you could say more about the scenario. The cleaner > should execute once the executor service is eligible to be GC'ed and the > reference is queued. Invoking shutdown just means it is early > unregistered. So I'm wondering if your issue is more about timing in > that it's not being GC'ed in a timely manner. > > -Alan >