-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Daniel Mikusa opened SPR-9084 and commented
Given a Spring MVC application which uses the Spring Forms JSP tags for data binding, a page that has a large number of field can cause blocking to occur.
Attached is a thread dump from an actual application which is experiencing this problem. Also attached is a sample application which can be used to demonstrate the problem.
To run the demo, use the command "mvn:tomcat". Once the application is deployed to Tomcat, run the included JMeter test to put load on the application. As the JMeter test runs, you should see the "max" time gradually increasing. I let it run for about 5 minutes and the max time crept up to around 10 seconds per response. Taking a thread dump at this time should show the issue.
In addition, I've ran the demo, replicating the problem, and have taken a snapshot with YourKit. The snapshot is attached.
From the snapshot, it appears that a significant portion of the contention appears to be around the following two items:
http-8080-8 [BLOCKED] CPU time: 0:03
java.util.Collections$SynchronizedMap.get(Object)
org.springframework.core.GenericTypeResolver.getTypeVariableMap(Class)
org.springframework.core.GenericTypeResolver.resolveParameterType(MethodParameter, Class)
org.springframework.core.convert.Property.resolveParameterType(MethodParameter)
org.springframework.core.convert.Property.resolveReadMethodParameter()
org.springframework.core.convert.Property.resolveMethodParameter()
org.springframework.core.convert.Property.<init>(Class, Method, Method)
org.springframework.beans.BeanWrapperImpl.property(PropertyDescriptor)
org.springframework.beans.BeanWrapperImpl.getPropertyTypeDescriptor(String)
org.springframework.validation.AbstractPropertyBindingResult.formatFieldValue(String, Object)
org.springframework.validation.AbstractBindingResult.getFieldValue(String)
org.springframework.web.servlet.support.BindStatus.<init>(RequestContext, String, boolean)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus()
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath()
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName()
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId()
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId()
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(TagWriter)
org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(TagWriter)
org.springframework.web.servlet.tags.form.InputTag.writeTagContent(TagWriter)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal()
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag()
org.apache.jsp.WEB_002dINF.views.home_jsp._jspx_meth_form_005finput_005f0(JspTag, PageContext, int[])
org.apache.jsp.WEB_002dINF.views.home_jsp._jspService(HttpServletRequest, HttpServletResponse)
org.apache.catalina.core.ApplicationDispatcher.forward(ServletRequest, ServletResponse)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(Map, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.view.AbstractView.render(Map, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.render(ModelAndView, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.doService(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.FrameworkServlet.processRequest(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.FrameworkServlet.doPost(HttpServletRequest, HttpServletResponse)
java.lang.Thread.run()
and
http-8080-18 [BLOCKED] CPU time: 0:00
java.util.Arrays.equals(Object[], Object[])
org.springframework.util.ObjectUtils.nullSafeEquals(Object, Object)
org.springframework.core.convert.TypeDescriptor.equals(Object)
org.springframework.core.convert.support.GenericConversionService$ConverterCacheKey.equals(Object)
java.util.concurrent.ConcurrentHashMap.get(Object)
org.springframework.core.convert.support.GenericConversionService.getConverter(TypeDescriptor, TypeDescriptor)
org.springframework.core.convert.support.GenericConversionService.canConvert(TypeDescriptor, TypeDescriptor)
org.springframework.validation.AbstractPropertyBindingResult.formatFieldValue(String, Object)
org.springframework.validation.AbstractBindingResult.getFieldValue(String)
org.springframework.web.servlet.support.BindStatus.<init>(RequestContext, String, boolean)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus()
org.springframework.web.servlet.tags.form.ErrorsTag.shouldRender()
org.springframework.web.servlet.tags.form.AbstractHtmlElementBodyTag.writeTagContent(TagWriter)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal()
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag()
org.apache.jsp.WEB_002dINF.views.home_jsp._jspService(HttpServletRequest, HttpServletResponse)
org.apache.catalina.core.ApplicationDispatcher.forward(ServletRequest, ServletResponse)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(Map, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.view.AbstractView.render(Map, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.render(ModelAndView, HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.doService(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.FrameworkServlet.processRequest(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.FrameworkServlet.doPost(HttpServletRequest, HttpServletResponse)
java.lang.Thread.run()
The first item appears to be similar to what is mentioned here in #13343. The second item appears to be unique.
Affects: 3.0.6, 3.1 GA
Attachments:
- BindingSyncTest.zip (26.94 kB)
- Launcher-2012-02-01-shutdown-2.snapshot.zip (1.82 MB)
- threaddump-1326467408882.tdump (812.05 kB)
Referenced from: commits 17bbc62, 9e21d2f
2 votes, 2 watchers