Register a listener of type HttpSessionListener in web.xml. Make it log calls to sessionCreated() and sessionDestroyed(). Invoke a servlet to create new HTP session. Within the servlet code set session timeout to something like 5 seconds. Close client app. Slowly count to 5. See the listener's log. Expected: one call to sessionCreated() and one to sessionDestroyed().\ Actual: one call to sessionCreated(), as expected, then two calls to sessionDestroyed(). In both calls to sessionDestroyed() event.getSession() returns reference to the same session object. Reason: HttpSessionListener receives sessionDestroyed() event twice. Here is a quote from org.apache.catalina.session.StandardManager: public void processExpires() { long timeNow = System.currentTimeMillis(); Session sessions[] = findSessions(); for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; if (!session.isValid()) { try { expiredSessions++; session.expire(); } catch (Throwable t) { log.error(sm.getString ("standardManager.expireException"), t); } } } long timeEnd = System.currentTimeMillis(); processingTime += ( timeEnd - timeNow ); } The problem, apparently is that session.expire() method is invoked not only direct from the above quoted method (StandardManager,java:815), but also session.isValid() method. I am not familiar with Tomcat codebase to try and suggest a fix, but a method called "isValid" doing something other than assessing and reporting the session state to its caller seems strange.
*** This bug has been marked as a duplicate of 25234 ***