I have a jsp
file and a HttpSessionListener
to monitor HttpSession
destroying activities.
index.jsp
<%
HttpSession s = request.getSession();
System.out.println("SID1 : " + s.getId());
s.setAttribute("Key", "Value");
s.invalidate();
%>
SessionListener
@WebListener
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession s = se.getSession();
System.out.println("SID2 : " + s.getId());
System.out.println(s.getAttribute("Key"));
s.invalidate();
System.out.println("Session Destroyed");
}
}
Now according to the above situation, sending a HTTP request to index.jsp
should create a HttpSession
and call it's invalidate()
method, meanwhile the HttpSessionListener
should catch the same HttpSession
and call the invalidate()
once again, and this process should repeat over and over again.
Which should eventually result in throwing a java.lang.StackOverflowError
. But I have got the the following output without any errors.
SID1 : A2751AE9E782A17380415B0078C9ED90
SID2 : A2751AE9E782A17380415B0078C9ED90
Value
Session Destroyed
I have tested it with both GlassFish and Tomcat servers, the result stays the same. Can someone explain what's going on?
Apparently this is because session is already invalidated when you invoke invalidate
method for the second time from public void sessionDestroyed(HttpSessionEvent se) {...}
.
Session.beginInvalidate()
returns false
value in this case and this block is not invoked:
boolean result = beginInvalidate();
try {
//if the session was not already invalid, or in process of being invalidated, do invalidate
if (result) {
//tell id mgr to remove session from all contexts
_handler.getSessionIdManager().invalidateAll(_sessionData.getId());
}
}
In particular,_handler.getSessionIdManager().invalidateAll
invokes SessionHandler.invalidate
, which invokes SessionHandler.removeSession
which invokes _sessionListeners.get(i).sessionDestroyed(event);
.
So in case if the session is already invalidated this scenario doesn't work.