Issue
I came across part in Head First JSP and Servlets page:241 where it says that we have to get rid of sessions as shown in this picture: src="https://i.stack.imgur.com/6U7eA.png" alt="enter image description here" />
Later on they present methods invalidate()
and setMaxInactiveInterval()
that are used to reduce amount of stale sessions sitting in our server. After reading that, I got a little confused.
To start with, I get session object inside Servlet's code using HttpSession s = request.getSession()
and then do some operations. Knowing that one request will make one thread for that Servlet, means that variable s
will have scope only for that given thread. Once thread completes, variable s
won't exist. Which further means session object in heap won't have active reference from s
= garbage collected.
So in case there are no new requests, there shouldn't be any session object taking my resources, right? So why does the book tell me I have to get rid of them? Shouldn't garbage collector do its job alone?
Can someone correct me by saying what I wrote wrong? And are session objects really stored inside the heap? As I can't think of any other place where they could be.
Solution
There are quite e few things to unwrap here, so let's take them one by one.
Sessions and cookies
HTTP is a stateless protocol. What that means is that, for the server, each HTTP request is seen as independent for other HTTP requests. So if you make multiple requests to the same server, the server doesn't actually care if they come from the same client or not: a request is received and a response is generated, another request is received and another response is generated, and so on.
But there are however situations in which you need to identify a bunch of requests as coming from the same user as a longer interaction with the server, not just isolated requests. And here is where sessions and cookies come in.
A session identifies multiple interactions of the same user with the server and allows you to maintain the user identity and some useful data whose life time can span across all the requests. That means that a session is stateful as opposed to stateless.
A session is basically an object that the server holds in memory, that acts as a container for whatever data you want to save in between requests. This object can also be persisted on disk or inside a database (like for example, when you restart the server and don't want to lose the active sessions), but for the sake of simplicity just consider it an in memory object. And yes, it is stored inside the HEAP.
So, at the server, you can create a session object if your application needs to store state in between requests. But how do you identify the requests that belong to one session from other requests that don't belong to that session? The answer is cookies.
When an user makes their first request, the server can creates a session and give you back a SESSION_ID that gets added to the response. When the user then makes another request, the SESSION_ID is sent back to the server and now this request is identified as being part of a larger interaction, part of a session. Which session? That identified with the SESSION_ID. So the session is an object stored at the server and any requests that are part of that session interaction need to be identified with the SESSION_ID.
Garbage collecting sessions
Since the session object is a Java object that lives on the HEAP, it can be garbage collected. However, it's not that simple.
Compare for example the following pieces of code. This:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
Object s = new Object();
// ...
}
with this:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
HttpSession s = request.getSession();
// ...
}
In the first example, you create an object that is stored on the HEAP. Once the doGet
method ends, this object is eligible for garbage collection because there are no more references to the object apart from s
which goes out of scope when the method returns.
The key part here is "no more references". An object is eligible for garbage collection when the object can no longer be accessed from any of the live references that exist inside the JVM. When the doGet
method ends, s
is gone, so nothing points to the object you created. With a HttpSession
things are different.
In the second piece of code, you don't create a session object, you ask the server to "give you" a session object. Imagine a Map retained by the server that contains session objects as values and SESSION_IDs are the keys to access them. When you ask the server to give you a session with HttpSession s = request.getSession()
what it does is look at the SESSION_ID cookie from the request to look for a session associated with that request and give you a reference to the session object. Now you have two references to the session object, one held by the server in that Map of sessions, and one you store in s
. When the doGet
method ends, the s
reference is gone, but the server still holds a reference to the session object (because it needs it for further requests that may arrive as part of the larger interaction). In this case, the session object is NOT eligible for garbage collection because it's reachable by a live reference within the JVM, the one held by the server.
So, if you don't get rid of sessions, the server has no way of knowing if that session is useful or useless because it doesn't know if there will be another request made later on to ask for it or not. So the session objects stay in the server forever. With a server being able to run for months or years without ever being restarted or shut down, the session objects can accumulate and consume all the memory. The garbage collector won't remove them because there are references to them hold by the server. You eventually get an OutOfMemory error and your server crashes.
Session timeouts
Of course, you don't want your server to crash. So you need to invalidate the sessions and tell the server that "Hey, I don't need that session object anymore. You can get rid of it". In that case the server removes it from its Map, and without any live references, it can now be garbage collected.
But since all this interaction happens over the network with HTTP, like the example in the book mentions, the browser can crash, the user's computer can crash, the user can just simply go away. So you might not get a chance to invalidate the session and tell the server it's OK to dispose of it, so it will stay there forever.
And here is where session timeouts come in. When you build your application, you also configure a session timeout to tell the server "Hey, if there is an inactivity on this session for X minutes, you can get rid of it". So now, if the client just goes away without invalidating the session, the server can have a fail safe mechanism to get rid of expired session so that they don't stick around forever in memory.
Answered By - Bogdan
Answer Checked By - Willingham (JavaFixing Volunteer)