DWR同時異常
6969 ワード
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();
synchronized (sessionLock)
{
DefaultScriptSession scriptSession = (DefaultScriptSession) sessionMap.get(id);
if (scriptSession == null)
{
scriptSession = new DefaultScriptSession(id, this);
* sessionMap.put(id, scriptSession);*
}
else
{
scriptSession.updateLastAccessedTime();
}
return scriptSession;
}
}
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();
http://pengtyao.iteye.com/blog/1074271
conCurrentHashMap iterator
http://stackoverflow.com/questions/3768554/is-iterating-concurrenthashmap-values-thread-safe