迭代Grails参数映射时出现间歇性ConcurrentModificationException

时间:2015-06-14 14:25:30

标签: grails concurrentmodification

我偶尔会在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。

0 个答案:

没有答案