Spring AspectJ AOP 和 redirect ModelAndView 导致的内存泄漏问题
今天遇到一个缓慢内存泄漏的问题, 经查, 与 Spring MVC 的 redirect 使用相关.
如果使用了 Spring 的 Spring AspectJ AOP 和 ModelAndView, 并且在 redirect 的时候, 是如下面的跳转, 就可能有缓慢内存泄漏的问题.
当 redirect 时候, redirect 的 URL 是变化的时候, 就会出现内存泄漏, 比如下面的代码:
String redirectUrl = "id=" + String.valueOf(Math.random());
return new ModelAndView(String.format("redirect:%s", redirectUrl));
原因是: 在页面解析的时候, 这个 ModelAndView 会被 Spring 重新生成一个 RedirectView, 这个 RedirectView 被 Spring 生成之后, 会执行一个 postProcessAfterInitialization 方法, 如果这时候是使用 AspectJ AOP, 那么 AspectJ 会把生成的一个 bean 放入一个 全局唯一的 ConcurrentHashMap里面, 放的时候以 bean.getClass() + beanName 作为 key. 然而对于 RedirectView, 这个 beanName 正是这个 redirect 的 URL, 如果它是一个变化的值, 那么就会持续添加. 代码:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
发生添加的Stack trace 如下, 可以进行 debug 验证: