52818 java.util.ConcurrentModificationException 52819 at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) 52820 at java.util.HashMap$ValueIterator.next(HashMap.java:822) 52821 at org.directwebremoting.impl.DefaultScriptSessionManager.checkTimeouts(DefaultScriptSessionManager.java:179) 52822 at org.directwebremoting.impl.DefaultScriptSessionManager.maybeCheckTimeouts(DefaultScriptSessionManager.java:163) 52823 at org.directwebremoting.impl.DefaultScriptSessionManager.getScriptSession(DefaultScriptSessionManager.java:50) 52824 at org.directwebremoting.impl.DefaultWebContext.getScriptSession(DefaultWebContext.java:83) 52825 at org.directwebremoting.dwrp.BaseCallMarshaller.marshallOutbound(BaseCallMarshaller.java:305) 52826 at org.directwebremoting.servlet.PlainCallHandler.handle(PlainCallHandler.java:53) 52827 at org.directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:101) 52828 at org.directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:146) 52829 at com.netease.photo.webapp.web.servlets.PhotoDwrServlet.doPost(PhotoDwrServlet.java:51) 52830 at javax.servlet.http.HttpServlet.service(HttpServlet.java:709) 52831 at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) 52832 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) 52833 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) 52834 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265) 52835 at com.netease.photo.security.filter.NEAccessInfoFilter.doFilter(NEAccessInfoFilter.java:55) 52836 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275) 52837 at com.netease.photo.security.filter.NEFilterSecurityInterceptor.doFilter(NEFilterSecurityInterceptor.java:49) 52838 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275) 52839 at com.netease.photo.security.filter.NEAnonymousProcessingFilter.doFilter(NEAnonymousProcessingFilter.java:234) 52840 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275) 52841 at com.netease.photo.security.filter.NEAuthenticationProcessingFilter.doFilter(NEAuthenticationProcessingFilter.java:300) 52842 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275) 52843 at com.netease.photo.security.filter.NEExceptionTranslationFilter.doFilter(NEExceptionTranslationFilter.java:62)
问题代码,报出异常原因是sessionMap有变化,导致modCount和expectedModCount不相等,判断了checkForComodification()后,抛出异常 protected void checkTimeouts() { long now = System.currentTimeMillis(); List timeouts = new ArrayList();
synchronized (sessionLock) { for (Iterator it = sessionMap.values().iterator(); it.hasNext();) { DefaultScriptSession session = (DefaultScriptSession) it.next();
if (session.isInvalidated()) { continue; }
long age = now - session.getLastAccessedTime(); if (age > scriptSessionTimeout) { timeouts.add(session); } }
for (Iterator it = timeouts.iterator(); it.hasNext();) { DefaultScriptSession session = (DefaultScriptSession) it.next(); session.invalidate(); } } }
具有改变sessionMap的源码 public RealScriptSession getScriptSession(String id) { maybeCheckTimeouts();
protected void invalidate(RealScriptSession scriptSession) { // Can we think of a reason why we need to sync both together? // It feels like a deadlock risk to do so synchronized (sessionLock) { *RealScriptSession removed = (RealScriptSession) sessionMap.remove(scriptSession.getId());* if (!scriptSession.equals(removed)) { log.debug("ScriptSession already removed from manager. scriptSession=" + scriptSession + " removed=" + removed); }
int removeCount = 0; for (Iterator it = pageSessionMap.values().iterator(); it.hasNext();) { Set pageSessions = (Set) it.next(); boolean isRemoved = pageSessions.remove(scriptSession);
if (isRemoved) { removeCount++; } }
if (removeCount != 1) { log.debug("DefaultScriptSessionManager.invalidate(): removeCount=" + removeCount + " when invalidating: " + scriptSession); } } }
http://directwebremoting.org/jira/browse/DWR-536 这个是我们遇到的问题. The problem is when using an iterator of a synchonized map; when using an iterator, the map (even when it is synchronized) should be synchronized while iterating... 即使对hashmap外部做了synchronized,在iterator的时候hashmap还是不安全的。(这里不安全的原因还在调查,估计跟jvm有关) 有两种解决方案 1.对hashmap在iterator之前做一次拷贝 2.对hashmap做同步,可以使用concurrenthashmap
在dwr后面的几次版本更新中已经有了修改 /* */ protected final ConcurrentMap sessionMap; /* */ protected final ConcurrentMap> pageSessionMap;
/* 527 */ this.sessionMap = new ConcurrentHashMap(); /* */ /* 535 */ this.pageSessionMap = new ConcurrentHashMap();
[code="java"]52818 java.util.ConcurrentModificationException52819 at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)52820 at java.util.HashMap$ValueIterator.next(HashMap.java:...