From 85f39b4f1c59ddf7182ffa08b089dc8875e9ec6e Mon Sep 17 00:00:00 2001 From: Marvin Froeder Date: Wed, 18 Mar 2026 06:59:39 -0300 Subject: [PATCH] Replace static ExecutorService singleton with per-instance executor to fix ClassLoader leak (#3178) Signed-off-by: Marvin Froeder --- core/src/main/java/feign/AsyncFeign.java | 19 ++++++++----------- .../java/feign/kotlin/CoroutineFeign.java | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/feign/AsyncFeign.java b/core/src/main/java/feign/AsyncFeign.java index 67948dd46..8f9c17f9b 100644 --- a/core/src/main/java/feign/AsyncFeign.java +++ b/core/src/main/java/feign/AsyncFeign.java @@ -55,23 +55,20 @@ public static AsyncBuilder asyncBuilder() { return builder(); } - private static class LazyInitializedExecutorService { - - private static final ExecutorService instance = - Executors.newCachedThreadPool( - r -> { - final Thread result = new Thread(r); - result.setDaemon(true); - return result; - }); + private static ExecutorService newDefaultExecutorService() { + return Executors.newCachedThreadPool( + r -> { + final Thread result = new Thread(r); + result.setDaemon(true); + return result; + }); } public static class AsyncBuilder extends BaseBuilder, AsyncFeign> { private AsyncContextSupplier defaultContextSupplier = () -> null; private AsyncClient client = - new DefaultAsyncClient<>( - new DefaultClient(null, null), LazyInitializedExecutorService.instance); + new DefaultAsyncClient<>(new DefaultClient(null, null), newDefaultExecutorService()); private MethodInfoResolver methodInfoResolver = MethodInfo::new; @Deprecated diff --git a/kotlin/src/main/java/feign/kotlin/CoroutineFeign.java b/kotlin/src/main/java/feign/kotlin/CoroutineFeign.java index 4027e1d14..d974732f2 100644 --- a/kotlin/src/main/java/feign/kotlin/CoroutineFeign.java +++ b/kotlin/src/main/java/feign/kotlin/CoroutineFeign.java @@ -49,15 +49,13 @@ public static CoroutineBuilder coBuilder() { return builder(); } - private static class LazyInitializedExecutorService { - - private static final ExecutorService instance = - Executors.newCachedThreadPool( - r -> { - final Thread result = new Thread(r); - result.setDaemon(true); - return result; - }); + private static ExecutorService newDefaultExecutorService() { + return Executors.newCachedThreadPool( + r -> { + final Thread result = new Thread(r); + result.setDaemon(true); + return result; + }); } private static class CoroutineFeignInvocationHandler implements InvocationHandler { @@ -119,8 +117,7 @@ public static class CoroutineBuilder private AsyncContextSupplier defaultContextSupplier = () -> null; private AsyncClient client = - new DefaultAsyncClient<>( - new DefaultClient(null, null), LazyInitializedExecutorService.instance); + new DefaultAsyncClient<>(new DefaultClient(null, null), newDefaultExecutorService()); private MethodInfoResolver methodInfoResolver = KotlinMethodInfo::createInstance; @Deprecated