fix: remove static ExecutorService in AsyncFeign to prevent ClassLoader leak#3308
Closed
anuragg-saxenaa wants to merge 1 commit intoOpenFeign:masterfrom
Closed
Conversation
… ClassLoader leaks AsyncFeign used a LazyInitializedExecutorService inner class to hold a static singleton ExecutorService. In servlet containers (Tomcat, Jetty), redeploying an application does not restart the JVM. The static thread pool retains a strong reference to the ContextClassLoader of the first deployment, preventing it from being GC'd on subsequent redeployments. This causes ClassLoader leaks and eventual Metaspace OutOfMemoryError. The fix removes the static LazyInitializedExecutorService entirely. AsyncBuilder now creates a fresh per-instance executor in its default client field initializer. Users who need to share or control lifecycle of the executor should continue to supply their own via builder.client(). Fixes OpenFeign#3178 Signed-off-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Contributor
|
isn't it already covered in #3277? |
Author
|
Closing as duplicate of #3277 which addresses the same issue with a more complete fix (also covering CoroutineFeign). Thanks for the pointer @yvasyliev! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
AsyncFeignheld a static singletonExecutorServiceviaLazyInitializedExecutorService:In servlet containers (Tomcat, Jetty, etc.), redeploying an application does not restart the JVM. The static thread pool holds a strong reference to the
ContextClassLoaderof the first deployment. On each redeployment:ClassLoaderis never GC'd (retained by the static thread pool's threads)OutOfMemoryErrorSetting threads as daemon only helps at JVM exit — it does not prevent ClassLoader leaks during hot-redeploy.
Fix
Remove
LazyInitializedExecutorServiceentirely.AsyncBuilder.clientis now initialized with a freshExecutors.newCachedThreadPool(...)per builder instance. This means:AsyncFeign.builder()creates its own independent executor.client(AsyncClient)Testing
Added
asyncFeignHasNoStaticExecutorService()toAsyncFeignTest— uses reflection to assert that nostaticfield of typeExecutorServiceexists in any inner class ofAsyncFeign.Fixes #3178