Hello,
We are currently facing an issue when successive redeployments happen. We get an java.lang.OutOfMemoryError: Metaspace. On redeployment, new classloaders are created but there are soft references which are kept in ConcurrentReferenceHashMap across spring core. What we see as a general behavior is that softkeys are only freed on garbage collection if a certain memory threshold is reached in the heap memory. But there are cases where the keys retain classloaders which were dereferenced elsewhere on undeployment and in that case, if what is stressed is the metaspace we arrive to an OOM Metaspace because the softkeys are not freed in the heap memory.
We are currently considering to change the DEFAULT_REFERENCE_TYPE to WEAK through reflection, but taken into account the following comment:
https://github.com/spring-projects/spring-framework/issues/16021#issuecomment-453409588
Shouldn't spring provide a way to change the default reference type which is now private?
Thanks in advance
Comment From: bclozel
Sorry it took us so long to reply here.
I'm not sure changing the default reference type in ConcurrentReferenceHashMap
would really help here.
As far as I understand, by default the Metaspace memory is not limited and only the -XX:MaxMetaspaceSize
argument can limit it. This must be the case for this application. Also, while weak references tend to be collected as soon as they're not strongly reachable by anything else, soft references tend to stick around longer as they're collected when the heap is near its maximum size. Depending on the choice of GC, it seems that the Metaspace information should be collected during Full GC operations anyway, even if type information was not strongly reachable in regular GC sweeps.
What might happen here is that the MaxMetaspaceSize
is set too low and that the JVM has still plenty of memory space and didn't trigger a Full GC. If a Full GC was indeed triggered, both Soft references and unused classes would be collected. On the other hand, switching to weak references as a default for this cache would trash a lot of values and significantly reduce its efficiency.
I'm closing this issue as the best course of action is probably about GC tuning and not changing the defaults in Spring. Thanks!