我偶尔会在grails应用程序的CI中登录ConcurrentModificationException
。我认为这只会在应用程序负载很大的情况下发生(我们在同一个tomcat实例中触发8个并发的Geb测试分片)。
2015-06-14 13:44:16,702 [http-bio-8080-exec-53] ERROR errors.GrailsExceptionResolver - ConcurrentModificationException occurred when processing request: [POST] /myapp/task/getSchedules
Stacktrace follows:
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:394)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:413)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:412)
at com.myapp.controller.ControllerSearchService.getMostRecentPrefixedParams(ControllerSearchService.groovy:83)
at com.myapp.controller.ControllerSearchService.getMostRecentFilterParams(ControllerSearchService.groovy:65)
at com.myapp.controller.ControllerSearchService.advancedSearch(ControllerSearchService.groovy:239)
at com.myapp.aspect.ServiceMethodTimingAspect.traceServiceMethodCall(ServiceMethodTimingAspect.java:20)
at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
at com.myapp.task.TaskController.getSchedules(TaskController.groovy:287)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:150)
at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:285)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:198)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:176)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at com.myapp.organisation.security.RestAuthenticationFilter.doFilter(RestAuthenticationFilter.groovy:160)
at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:49)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
at com.odobo.grails.plugin.springsecurity.rest.RestLogoutFilter.doFilter(RestLogoutFilter.groovy:63)
at org.grails.jaxrs.web.JaxrsFilter.doFilterInternal(JaxrsFilter.java:46)
at com.brandseye.cors.CorsFilter.doFilter(CorsFilter.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
getMostRecentPrefixedParams
方法中的代码如下所示:
private def getMostRecentPrefixedParams(params, session, prefix, sessionParamName) {
synchronized (params) {
for (String key : params) { // line 83 - exception happens here
if (key.startsWith(prefix)) {
if (session != null) {
clearTags(params)
}
return params
}
}
}
if (session == null) {
return params
}
return session."${sessionParamName}" == null ? params : session."${sessionParamName}"
}
我添加了synchronized
块以试图阻止这种情况发生,但显然正在发生其他事情。
传递给params
方法的getMostRecentPrefixedParams
参数只来自控制器(隐式params
控制器属性) - 据我所知,只有一个请求线程应该在整个请求/响应周期中访问该映射,但即使不是这种情况而另一个线程以某种方式访问该映射,我会认为synchronized块会阻止{{1 }}
我们正在使用Grails 2.3.7。