More than 10 years of experience in Enterprise Applications development, and Project Management (since June 2001). Specialties: Enterprise Applications, J2EE, J2SE, Spring Framework, Spring Security, Spring Webflow, JPA and JDBC, JMX, JAXB, JUnit; XML, XSLT and XSL-FO; HTML/CSS, Javascript, JSON, jQuery/jQuery UI; RDBMS (Oracle, SQL Server, MySQL), PL/SQL; UML; Mobile Applications, mostly in Objective-C targeted iPhone/iPad Michal is a DZone MVB and is not an employee of DZone and has posted 12 posts at DZone. You can read more from them at their website. View Full User Profile

Spring's Web MVC - Redirect to the Memory Leak

12.10.2012
| 5011 views |
  • submit to reddit

They say that one rock can cause an avalanche. Lately, one of my Colleagues, Marcin Radoszewski, gave me such a rock. You'll probably never guess what it is, but there is a chance, that you use it in many of your Web Applications. Allow me to introduce this rock to you :)

You probably well know redirect after post pattern. Using Spring Framework you have few ways to implement it, let's focus on one of them, returning the target URL as the String with redirect: prefix.

Suppose that we have controller using this method of redirecting, and we have to pass some parameters during the redirect, let it be some entity ID for example:

@RequestMapping(method = RequestMethod.POST)
public String onPost(...) {
    ...
    return "redirect:form.html?entityId=" + entityId;
}
As you see, our rock doesn't look dangerous, it even doesn't look suspicious :) - What the heck is wrong with that?! - you may ask. Well, to explain that, we have to take a look at the way how Spring Framework handles the value returned by you.

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.

How soon that will kill my application? - you may ask. That depends on the amount of memory assigned to JVM, and the number of performed redirects :) - I've made some tests using: -Xmx64M option, with simple application build from only one controller - see this example. After about 76400 redirects the application died with OutOfMemoryError: Java heap space.
Published at DZone with permission of Michal Jastak, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Harald Wellmann replied on Mon, 2012/12/10 - 11:45am

 Looks like a bug in Spring. Did you or your colleague file an issue?

joshua long replied on Tue, 2012/12/11 - 12:49pm

Hi - please see this JIRA for ways to avoid this particular behavior. The caching works as expected, and there are ways to not incur the error, or disable caching all together. 

Michal Jastak replied on Thu, 2012/12/13 - 1:20am in response to: Harald Wellmann

 Yes, I did - AbstractCachingViewResolver - caching redirect views leads to memory leak   - Joshua Long has mentioned it above.

Michal Jastak replied on Thu, 2012/12/13 - 1:28am in response to: joshua long

 Regardless of other possible redirect methods (see comment made by Rossen in JIRA), which I agree are a way better than presented by me, using HashMap for caching without any size restriction is just asking for troubles :(

If memory leak is expected cache behavior, then Spring Framework guys wouldn't correct it ;)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.