New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible classloader leak through incomplete clearing of annotation caches #31170
Comments
We use |
In Since yesterday, I continued to learn :) "Unloading" classes in Java is a tricky topic apparently. Any Java application trying to support hot reloading is affected. I found for example some interesting code in the IntelliJ Platform, where they are trying to unload dynamic plugins classloaders. The "trick" they use is to saturate the memory to force the GC to release soft references. In the end, since unloading classloader is probably not a common use case, maybe that would be simpler to expose methods allowing to purging of those caches when needed, similar to |
Good point, and such a |
This turns out to be a regression from 4.3 since two new caches introduced in 5.2 where not part of |
We also reset our common infrastructure caches again in |
Thanks, that looks great! |
Hi,
We are using Spring 5.3.28 in our application. This application supports dynamic plugins, so we do something like this:
The issue I am facing is that even if I close properly the Spring context and the URLClassloader, there is still a class leak. If I run the previous code in a loop, I can see the metaspace and the number of loaded classes continuously increasing. Triggering a gc doesn't help.
The URLClassloader instance (and all associated classes) is never collected.
I tried to find the reason for this, and I might be wrong at this point, but here are my findings.
The leak seems to be caused by one (or all) of the caches that are used in Spring annotation processing. My understanding is that one class inside one of our plugin we later add as a bean is annotated with a custom annotation. This annotation is part of the plugin JAR, and so belongs to the plugin classloader. But Spring will store the annotation (and transitively the classloader I'm trying to free) in one of the static top-level annotations caches.
Am I on the right track?
I managed to unload properly my plugin only after doing this:
(not sure they are all required, I made so many attempts...)
Before I move further, do you have some insights to share? Shouldn't we have a clean way to clean all those caches?
I can probably provide a reproducer, but since this will need quite some effort, I want to be sure first I did not miss something obvious.
Thanks.
The text was updated successfully, but these errors were encountered: