I'm checking a Java Servlet tutorial, but I miss the information of when exactly the servlet is destroyed by the server?
and what if I want to destroy manually an unused Servlet to conserve a memory for other tasks!
Because as I know every server has its limit in memory and hosting unused servlets is wasting of resources and application quality,
Thank you to clarify this point because the application performance is one of the most important issue to care about during the development process!
There is only one instance of the Servlet on each node in multi-clustered environment or you can say there is only one instance of each Servlet on each JVM machine.
Servlet is initialized on application startup or at the first time when the servlet is invoked.
when exactly the servlet is destroyed by the server?
All the Servlet instances are destroyed when server is shutting down or on application disposal.
I want to destroy manually an unused Servlet to conserve a memory for other tasks!
You can't destroy the Servlet manually and Servlet is just like worker not for data container. In most of the cases Servlet doesn't contain any instance members to avoid multi-threading issues.
The Servlet specification does not say when a servlet must be shut down and destroyed, other than that it must be done before the container completes a normal shutdown. A container is otherwise permitted to remove an idle instance from service at its own discretion, as long as it is prepared to fire up a new instance later if one is needed.
The specification does not define a mechanism for forcing a servlet instance to be unloaded. It having been unloaded, reclaiming its resources (mostly memory) is the job of the garbage collector, and when that happens is difficult to influence.
Overall, these are exactly the kind of details that you choose Java technology to avoid worrying about. If you insist on worrying about them anyway then look to the documentation of your chosen servlet container -- if there is a supported way to do what you are after then you will find it documented there. Such a thing would be container-specific.
The container decides when to unload the servlet , this sequence releases any resources it is holding so that it can reacquire it if the servlet is loaded again.
the unloading sequence calls a servlet's destroy() method when the servlet is set to be unloaded. The destroy() method houses the clean up actions written by the servlet developer. In practice it should free any resources it has acquired that will not be garbage collected at this step. The destroy() method should also give the servlet a chance to write out its unsaved cached information or any persistent information that should be read during the next call to init().
if we call destroy() on servlet then it doesn't mean that our servlet will be unloaded. You can simply call the destroy method alone without unloading the servlet. However when the container decides to unload the servlet instance from memory then container runs destruction mechanism and destroy method is one of steps of the destruction mechanism.
The web container calls the destroy method when it needs to remove the servlet such as at time of stopping server or undeploying the project.
Related
I was reading the Servlet Specification and came across this:
For servlets not implementing the SingleThreadModel interface, if the service
method (or methods such as doGet or doPost which are dispatched to the service
method of the HttpServlet abstract class) has been defined with the synchronized
keyword, the servlet container cannot use the instance pool approach, but must
serialize requests through it.
I don't understand why the servlet container cannot use the instance pool approach with a synchronized service method. Doesn't the instance pool contain different instances of the servelet so that every instance will use itself to synchronize the method (not blocking each other)?
From what I understand the the synchronize will be useless in this case but it does not stop the servlet container from using an instance pool.
What am I missing?
Thanks.
What that sentence is saying is that if you dont implement SingleThreadModel then your Servlet instance wont be pooled at all no matter it it uses synchronization or not. The only reason it mentions synchronization is to warn you that Servlet container wont be using multiple instances of your Servlet per VM to allow it to process multiple requests at the same time.
Here is another missing fragment from the spec:
SRV.2.2 Number of Instances
The servlet declaration which is part of
the deployment descriptor of the Web application containing the
servlet, as described in Chapter SRV.13, “Deployment Descriptor”,
controls how the servlet container provides instances of the servlet.
For a servlet not hosted in a distributed environment (the default),
the servlet container must use only one instance per servlet
declaration. However, for a servlet implementing the SingleThreadModel
interface, the servlet container may instantiate multiple instances to
handle a heavy request load and serialize requests to a particular
instance. Servlet Life Cycle 19 In the case where a servlet was
deployed as part of an application marked in the deployment descriptor
as distributable, a container may have only one instance per servlet
declaration per Java Virtual Machine (JVMTM) 1 . However, if the
servlet in a distributable application implements the
SingleThreadModel interface, the container may instantiate multiple
instances of that servlet in each JVM of the container
This link says that earlier versions of Tomcat (before 7.0.54) "renews its threads" thru ThreadPoolExecutor.run().
Why doesn't the init() method of contained Servlets seem to get called again?
A Servlet is initialized only once, either at web application startup or upon first use.
The same instance will then be used to serve all incoming requests, if necessary even multiple requests at the same time (unless you use the deprecated option to synchronize access, but even then there will be just a single instance, and a queue of requests for it).
Having implemented a ContextListener I can now happily deal with contextDestroyed events by closing down my connection pools and flushing my caches etc.
I was surprised recently when contextDestroyed was called at a time when my server was not being shut down - it seemed to be at some arbitrary time which I have not been able to track down.
Is there any defined event or set of circumstances that trigger contextDestroyed?
Should I ensure that everything I do when contextDestroyed is called is reversible? Do I need to make all my pools survive a destroyed/initialized cycle? Was I wrong to assume I would only get a contextDestroyed when Tomcat was being shut down or my war was being replaced?
Through a series of trial and error testing I have found that contextDestroyed() is called when;
The server is .WAR is being updated/removed.
The server is shutdown due to administrator intervention.
The server is shutdown due to a coding error. Something that would
terminate a non-server application termination.
If you are experiencing issue #3, as you are suggesting, I think the best possible course of action is to safely (be sure not to create an infinite loop) call contextInitialized() to ensure pools are recreated properly.
See: http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
contextDestroyed(ServletContextEvent sce): Receives notification that
the ServletContext is about to be shut down.
I.e., it gets called when a web application gets unloaded (e.g., you remove or replace a .war file from the web-apps folder OR unload it using the Tomcat server-manager).
According to the java docs, it says that If SingleThreadModel is used there are two ways a servlet instance will be created and used
1. Create one servlet instance and make the service() method synchronized and thus allow only one thread to execute the service method.
2. Create a pool of servlets and serve the request by using one servlet instance from the pool for each request.
THe question which I want to ask is I have also read a new Servlet instance is created and destroyed for every request. Now which one is correct
Here's what the spec says (version 3.0, section 2.2):
For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the servlet container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.
In the case where a servlet was deployed as part of an application marked in the deployment descriptor as distributable, a container may have only one instance per servlet declaration per Java Virtual Machine (JVMTM)1. However, if the servlet in a distributable application implements the SingleThreadModel interface, the container may instantiate multiple instances of that servlet in each JVM of the container.
Note that you should really not use the single thread model. Just make sure your servlet is thread-sae. A servlet is typically stateless, so you don't have anything to do to make it thread-safe.
From the docs for SingleThreadModel:
Ensures that servlets handle only one request at a time
This is in essence a way to make non thread-safe servlet code work. Note that the container is free to choose any of the two implementations to adhere to the spec:
Create a single instance of the servlet and ensure that it handles only one request at a time
Create a pool of servlet instances and hand over a request to an available servlet instance.
I have an Initializer class that implements the ServletContextListener interface. In its contextInitialized() method, I initialize some global classes that have to be destroyed, otherwise the servlet cannot be unloaded.
However, when the servlet's init() method throws a ServletException, the contextDestroyed() method never gets called --> resources are not release --> servlet does not get unloaded by Tomcat (it remains in "running" state even though its init method never finished).
My question is this - how do I cleanup the resources in this case?
Bonus: why does the servlet even get to "running" state? I understand from the documentation that it's not supposed to be running unless the init() method finishes successfully.
Edit - I think this is because each status line displayed in Tomcat Manager represents an entire war, and not a servlet. A war may contain several servlets, with some succeeding to start and others not. The Initializer is called when the container starts, and its destroy is called only when the entire container is dropped. This leads to a related question - is there a similar built-in way to monitor the state of individual servlets?
(I'm aware I can write custom code to monitor the servlet, either via JMX, or not, but that's out of the scope of
this question).
As far as I can tell there's absolutely no way to do so without an external request. ServletContextListener gives you the correct signal (when all servlets have been initialized - successfully or not), but you can't enumerate all servlets in the context to test their status because the relevant ServletContext methods were deprecated and now return an empty enumerator.
In short, the only way to do this is via a nonstandard API; in particular, it's almost trivial to do this with Tomcat's JMX API, which is the course I'd recommend.
In real world the init() should never fail. If it fails, then it is a programming error which the developer is supposed to fix. The appserver webcontainer has nothing to do with it. The servlet will simply be kept unavailable.
What container are you running?
Tomcat for example does support JMX. You can always write your own JMX-beans.