`

探讨:spring mvc中redirect导致内存泄露?

 
阅读更多
在老外http://vard-lokkur.blogspot.com/2012/12/springs-web-mvc-redirect-to-memory-leak.html一文中,谈到了他发现的一个spring mvc 3以及之前版本可能存在的一个
redirect引起的内存泄露问题。例子为:

@RequestMapping(method = RequestMethod.POST)
public String onPost(...) {
    ...
    return "redirect:form.html?entityId=" + entityId;
}




  You may start from reading Resolving views in Spring Framework documentation, and then take a closer look at the source code of AbstractCachingViewResolver, which is base class for many different View Resolvers in Spring, including: JSP, FreeMarker, Velocity, Jasper Reports, Tiles and XSLT view resolvers.

When resolveViewName method is called on AbstractCachingViewResolver it uses HashMap based view cache to speed up view resolving in the future calls, and cache key is by default created using view name and current locale.

Now to the clue - when you use the above method of redirecting, Spring Framework uses the whole String returned from your controller's method as the view name, including all parameters included in the target URL. Each time you perform the redirect, the parameters may vary, thus such a redirect will leave one additional entry in view cache of  AbstractCachingViewResolver, causing memory leak.


    他认为,只要这个形式,多次的执行的话(他执行了7000多次),看JVM大小设置问题会导致内存泄露,原因他分析说,AbstractCachingViewResolver,这个代码是众多视图解析的父类了,
当 resolveViewName 方法调用AbstractCachingViewResolver时,使用的是hashmap
缓存去加速,而key是默认使用viewname和当前的locale.而spring当调用
redirect这个时候,使用的是整个从controller方法中返回的字符串,做为view name,包括你的目标url,所以导致了memory leak(但为什么呢?好像原文作者没具体分析出来)
      作者还在https://jira.springsource.org/browse/SPR-10065开了一个jira说明,
有兴趣的读者可以去看下。他测试的DEMO的例子在:
https://github.com/vardlokkur/webapp-02可以下载。
   不过可惜我在自己的机器上,chrome下执行7000多次,没发现有问题,但IE下执行到1040
次,没报错,但就停止了,很奇怪,大家可以探讨尝试下。
  
7
0
分享到:
评论
3 楼 tomgxf 2016-11-24  
感谢楼主提供的线索,旧版本的确有问题。
在框架升级的时候我们发现该问题在新版本的springmvc中已经得到解决。缓存的map添加了默认数量限制。
private final Map<Object, View> viewCreationCache =
			new LinkedHashMap<Object, View>(DEFAULT_CACHE_LIMIT, 0.75f, true) {
				@Override
				protected boolean removeEldestEntry(Map.Entry<Object, View> eldest) {
					if (size() > getCacheLimit()) {
						viewAccessCache.remove(eldest.getKey());
						return true;
					}
					else {
						return false;
					}
				}
			};
2 楼 jackyrong 2012-12-09  
是的,在老外的这个jira中,后来也说到了addAttribute的方法了,呵呵
1 楼 zfc827 2012-12-09  
这个问题确实存在,主要原因是因为 springmvc 会缓存 view 的key。关键代码如下:
public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver {
    /** Whether we should cache views, once resolved */
    private boolean cache = true;

    /** Map from view key to View instance */
    private final Map<Object, View> viewCache = new HashMap<Object, View>();

    //... set/get方法略

    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (!isCache()) {
            return createView(viewName, locale);
        } else { 
            Object cacheKey = getCacheKey(viewName, locale);
            synchronized (this.viewCache) {
                View view = this.viewCache.get(cacheKey);
                if (view == null && (!this.cacheUnresolved || !this.viewCache.containsKey(cacheKey))) {
                    // Ask the subclass to create the View object.
                    view = createView(viewName, locale);
                    if (view != null || this.cacheUnresolved) {
                        this.viewCache.put(cacheKey, view);
                        if (logger.isTraceEnabled()) {
                            logger.trace("Cached view [" + cacheKey + "]");
                        }
                    }
                }
                return view;
            }
        }
    }
}

以上代码定义了一个 cache的标识位,默认为 true,并定义了一个 Map 来缓存 View,
如果在 controller 返回的 view 是不固定的,如:"redirect:form.html?entityId=" + entityId,由于 entityId 的值会存在 N 个,那么会导致产生 N 个 ViewName 被缓存起来。
由于内存大小是有限的,所以当 N 大到一定数量时,会产生内存溢出。

个人认为,这并不能算是 spring 的bug,更多的应当是我们的使用方式导致。
为了解决这个问题,spring 提供了其他的方案:http://static.springsource.org/spring-framework/docs/3.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#mvc-ann-redirect-attributes

方法修改如下:
@RequestMapping(method = RequestMethod.POST)  
public String onPost(RedirectAttributes redirectAttrs) {  
    // ...
    redirectAttrs.addAttribute("entityId", entityId)
    return "redirect:form.html?entityId={entityId}";  
} 

如上,使用占位符后, viewName 的数量被限制为了1个。

相关推荐

    spring学习: spring mvc在redirect请求中传递数据

    标题中的“spring学习:spring mvc在redirect请求中传递数据”指的是在Spring MVC框架中,如何在重定向(Redirect)请求过程中传递参数。这通常涉及到HTTP响应的状态码、重定向URL以及模型数据的处理。在Spring MVC...

    25号05: Spring MVC1课堂内容

    在"25号05:Spring MVC1课堂内容"中,我们可以推测这是一个教学资源,涵盖了Spring MVC的基础到进阶知识,可能包括了从版本v01到v02的更新内容,特别是针对测试类的优化和使用。 1. **Spring MVC 概述**: Spring ...

    spring mvc重定向导致内存溢出解决方案

    在Spring MVC框架中进行页面重定向操作时,可能会遇到因重定向导致的内存溢出问题。本文将详细介绍该问题的原因、原理以及解决方法。 #### 一、问题背景及原因分析 在Spring MVC中使用重定向功能时,可以通过`...

    spring mvc 4.0

    在Spring MVC 4.0版本中,它引入了许多改进和新特性,以提升开发效率和应用程序的性能。 1. **依赖注入**:Spring MVC 4.0继续支持Spring框架的核心功能,依赖注入(DI),允许开发者通过配置来管理对象及其依赖...

    SpringMVCDemo:Spring MVC 框架知识案例

    1.创建第一个 Spring MVC 程序案例 2.Spring MVC @RequestMapping 注解案例 3.Spring MVC 请求参数的获取案例 4.Spring MVC 域对象共享数据案例 5.Spring MVC @ModelAttribute 注解案例 6.Spring MVC 国际化案例 7....

    读书笔记:Spring MVC实战.zip

    读书笔记:Spring MVC实战

    Spring MVC jar包

    Spring MVC 是一个基于Java的轻量级Web应用框架,它为开发者提供了模型-视图-控制器(MVC)架构,使开发人员能够更好地组织和分离应用程序的业务逻辑、数据处理和用户界面。Spring MVC是Spring框架的一个核心组件,...

    Spring MVC 到底是如何工作的?1

    下面将深入探讨 Spring MVC 的工作原理。 DispatcherServlet 的角色 在 Spring MVC 中,DispatcherServlet 是核心组件,负责处理所有的 HTTP 请求。它是 Spring MVC 框架的门面,负责将请求分配给合适的控制器,并...

    Spring mvc5.0.3 所有jar包

    下面我们将深入探讨Spring MVC 5.0.3中的关键知识点。 1. **DispatcherServlet**: 作为Spring MVC的核心组件,DispatcherServlet负责接收HTTP请求,然后根据配置的映射规则将请求分发到相应的处理器(Controller)...

    spring-mvc-官方中文文档

    Spring MVC 是 Spring 框架的一个重要组成部分,用于构建基于 Java 的 Web 应用程序。这个官方中文文档详细地介绍了如何使用 Spring MVC 来开发高效、可维护的 MVC(Model-View-Controller)架构的应用。Spring MVC ...

    spring学习: spring mvc上传文件方法分析

    本文将深入探讨Spring MVC中的文件上传方法,并基于提供的“spring学习:spring mvc上传文件方法分析”标题进行详细的解析。 首先,理解Spring MVC处理文件上传的基本流程至关重要。当用户在表单中选择文件并提交时...

    spring学习: spring mvc基础

    本篇文章将深入探讨Spring MVC的基础知识,包括它的核心概念、配置以及如何在实际项目中运用。 首先,我们需要理解Spring MVC的基本架构。它主要由DispatcherServlet、Controller、Model、View和ViewResolver等关键...

    spring-webmvc-5.0.8.RELEASE-API文档-中文版.zip

    赠送jar包:spring-webmvc-5.0.8.RELEASE.jar; 赠送原API文档:spring-webmvc-5.0.8.RELEASE-javadoc.jar; 赠送源代码:spring-webmvc-5.0.8.RELEASE-sources.jar; 赠送Maven依赖信息文件:spring-webmvc-5.0.8....

    开源测试项目:spring mvc+springsecurity3+ehcache+bootstrap+mysql

    开源测试项目:spring mvc+springsecurity3+ehcache+bootstrap+mysql 内附MySQL表,直接导入就可运行 效果图请移步:http://blog.csdn.net/yangxuan0261/article/details/10053947

    Spring MVC框架的各种依赖包下载

    下面我们将深入探讨Spring MVC框架的关键组成部分及其相关知识点。 1. **Spring Framework基础**:Spring是一个开源的Java平台,它提供了全面的编程和配置模型,以简化企业级应用的开发。Spring MVC是Spring框架的...

    Spring MVC 4.2.3

    在"Spring MVC 4.2.3"版本中,我们看到了一系列的功能改进和优化,以提升开发效率和应用性能。 首先,让我们深入了解Spring MVC的基础架构。模型(Model)负责存储应用的数据,视图(View)用于展示这些数据,而...

    spring mvc

    Spring MVC 是一个基于Java的轻量级Web应用框架,它属于Spring框架的一部分,主要用于构建控制器层,实现模型-视图-控制器(Model-View-Controller)架构。在Spring MVC中,开发者可以方便地处理HTTP请求,进行数据...

    spring3.0 MVC中文教程

    3. **第3部分:在Spring 3.0 MVC中进行表单处理** - 探讨如何使用Spring MVC处理表单提交,包括数据绑定和验证。 4. **第4部分:Spring 3 MVC的Tiles支持与Eclipse中的插件教程** - Tiles框架是一种用于管理页面布局...

    spring mvc项目后端源码

    下面我们将深入探讨 Spring MVC 的关键概念和相关知识点。 1. **DispatcherServlet**:Spring MVC 的入口点,它是一个前端控制器,负责接收请求,分发到相应的处理器。在项目中,通常在 web.xml 配置文件中定义 ...

Global site tag (gtag.js) - Google Analytics