Fix memory leak on AOP Proxy class definition cache.

How to reproduce

  1. Like @Validated annotation with Request scope Controller like bellow
// Annnotation definition
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Controller
@Scope(WebApplicationContext.SCOPE_REQUEST)
@RequestMapping(method = { RequestMethod.GET, RequestMethod.HEAD })
@Transactional
@Validated
public @interface MyController {
}

@MyController
public class RootController {
    @ModelAttribute("requireJs")
    public boolean isRequireJs() {
        return true;
    }

    @RequestMapping("/search")
    public String search(
        Model model, 
        @RequestParam(value = "space", required = false) @Max(value=100) String space) {
        // ommit
    }
}
  1. Aop class definition cache won't work well, therefore memory leak

Why

this bug is intruced by:

  • https://github.com/spring-projects/spring-framework/pull/26017/files#diff-8b811560ae60c9f7937f0d378880f1b4366fa67ea7024db018931a26e3b449edL370-L376
  • https://github.com/spring-projects/spring-framework/pull/26017/files#diff-dd90aa36a7221a652e04631ac19dcb6693a9c841e43a90d36cc3caa51121630eL945-L947

  • Because @Validated annotation added, AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization add advice for @Validated

  • Before https://github.com/spring-projects/spring-framework/pull/26017/, cache in org.springframework.cglib.core.AbstractClassGenerator works well. Because org.springframework.aop.framework.AdvisedSupport#getConfigurationOnlyCopy copy org.springframework.aop.framework.AdvisedSupport#advisorsArray for create copy instance.

But after https://github.com/spring-projects/spring-framework/pull/26017/, use same reference of org.springframework.aop.framework.AdvisedSupport#advisors for create copy instance. and this advitors field update by AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization

  1. When Create Aop class instance, try to reuse cache for class definition

Cache key is defined below code:

  • org.springframework.cglib.proxy.Enhancer#createClass
  • org.springframework.cglib.proxy.Enhancer#createHelper

org.springframework.cglib.proxy.Enhancer#filter is registered at https://github.com/spring-projects/spring-framework/blob/main/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java#L201-L202

  1. cache miss for class definition, memory leak happen At AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization, advice object updated and therefore cache key is pollute, cache miss and memory leak happen. memoryleak

So, When creating copy instance on org.springframework.aop.framework.AdvisedSupport#getConfigurationOnlyCopy, It is good that create new instance of ArrayList and copy all advices.

This bug reported by @hikoma Thanks!

Comment From: sbrannen

Thanks for the PR and the detailed report.

We'll look into it.

Comment From: sbrannen

Related issues:

  • 26266

  • 27395