开发者

contextDestroyed() vs addShutdownHook()

开发者 https://www.devze.com 2023-03-25 05:16 出处:网络
I\'m currently implementing ServletContextListener and using contextDestroyed() to r开发者_Go百科un cleanup tasks on my web application before it shuts down.However, I\'ve been reading about how Runti

I'm currently implementing ServletContextListener and using contextDestroyed() to r开发者_Go百科un cleanup tasks on my web application before it shuts down. However, I've been reading about how Runtime.addShutdownHook(Thread) can be used for the same purpose.

Is there any difference between these two methods of running cleanup before undeployment? Which is preferable for a web application, in terms of functionality, efficiency, and maintainability?


I think the ServletContextListener is more appropriate for a web application, because you clean up resources for each and every session.

A shutdown hook is executed with the JVM is shut down. That would be when you stop your container, which is a one-time event.


The danger with using addShutdownHook() is that you will likely get a classloader leak which will become apparent when you redeploy you app multiple times.

Because the shutdown hook's class (either a Thread subclass or a Runnable implementation in your webapp) is coming from your webapp's classloader, even after your webapp is undeployed by the container, the shutdown hook will still be registered with the system. This means the entire webapp's classloader cannot be garbage collected.

I'd definitely recommend ServletContextListener.


Many servlet containers support operations for dynamically dropping and/or reloading WARs without shutting down the JVM process. Thus if you if you write your cleanup routine as a ServletContextListener, it could potentially be run several times during the life of the container. (For example, if you modify and reload your WAR several times while the container process is still up.)

However, if you implement your cleanup using Runtime.addShutdownHook, it will run only once: when the JVM for the container as a whole is shut down.

ServletContextListener is probably the right answer for you, as it couples your cleanup routine with the life of the web application, as opposed to the life of the container process which is hosting it.


The leak which we are talking about will only happen if we do the hot/deployment. However, if server is restarted after every deployment change than hook should work fine without memory leak. Also, one more factor governing leak is type of resource cleaning you are trying to control via listener/hook.


Why not do both? While ServletContextListener is more appropriate for a webapp, I find that during development the server is often stopped abruptly and then contextDestroyed() is never called, so you can have both mechanisms in place to ensure there is always a graceful shutdown:

Implement a ServletContextListener where contextInitialized calls addShutdownHook() and contextDestroyed calls removeShutdownHook(). The hook and contextDestroyed can both delegate to some internal method to actually do the cleanup.

This way, if the listener is invoked properly then the hook gets added and removed (but not invoked) and there is no leak, but if the server dies without the context being destroyed, the shutdown hook cleans things up.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号