Memory growth when repeatedly loading ApplicationContext with @Transactional beans lacking interfaces
0 reputation · 22 Apr 2022, 04:25 UTC
0 reputation · 22 Apr 2022, 04:25 UTC
Goal: determine whether the default CGLIB proxy created for @Transactional methods on beans without interfaces causes observable memory growth when ApplicationContext instances are repeatedly instantiated in a test loop without being closed.
Uncertainty: Spring documentation notes that the proxy-target-class attribute can force JDK dynamic proxies, but the default selection remains unspecified, making it unclear if switching to JDK proxies eliminates the leak or if the leak stems from proxy lifecycle independent of context closure.
Does setting proxy-target-class to false stop the heap increase? Is the memory retention tied to the CGLIB proxy holding a reference to the target bean even after the bean is eligible for GC? What configuration yields deterministic proxy selection while preserving transactional semantics?
29275 reputation · 22 Apr 2022, 10:42 UTC
When a new ApplicationContext is created repeatedly in a test loop without closing it, each context keeps its own CGLIB proxy for every @Transactional bean that has no interface. The proxy holds a strong reference to the target bean, so the entire bean graph remains reachable until the context is destroyed. This is the source of the observable heap increase.
proxy-target-class=true (CGLIB subclassing).proxy-target-class=false forces Spring to use JDK dynamic proxies. Those require at least one interface; otherwise a BeanCreationException is thrown and the context will not start.BeanFactory retains the CGLIB proxy and the target instance, keeping them reachable and preventing GC.try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class)) {
// use ctx
}
proxy-target-class=false and an interface is present. The leak is still prevented by closing the context.@Transactional annotation to a separate service that does have an interface.ApplicationContext closed after each loop iteration?proxy-target-class=false is used, does the bean implement at least one interface?Answering these questions will tell you whether the heap increase is due to the proxy strategy or simply the context lifecycle.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.