contextDestroyed()vs addShutdownHook()

时间:2011-08-05 01:10:16

标签: java application-shutdown servlet-listeners

我目前正在实施ServletContextListener并使用contextDestroyed()在关闭之前在我的网络应用程序上运行清理任务。但是,我一直在阅读Runtime.addShutdownHook(Thread)如何用于同一目的。

在取消部署之前,这两种运行清理方法有什么区别吗?对于Web应用程序而言,哪个在功能,效率和可维护性方面更受欢迎?

5 个答案:

答案 0 :(得分:8)

我认为ServletContextListener更适合Web应用程序,因为您为每个会话清理资源。

在关闭JVM的情况下执行关闭挂钩。那就是当你停止你的容器时,这是一次性事件。

答案 1 :(得分:4)

使用addShutdownHook()的危险在于,当您多次重新部署应用程序时,您可能会遇到类加载器泄漏。

因为关闭钩子的类(你的webapp中的一个Thread子类或一个Runnable实现)来自你的webapp的类加载器,即使在你的webapp被容器取消部署之后,关闭钩子仍将在系统中注册。这意味着整个webapp的类加载器不能被垃圾收集。

我肯定会推荐ServletContextListener。

答案 2 :(得分:3)

许多servlet容器支持动态删除和/或重新加载WAR的操作,而无需关闭JVM进程。因此,如果您将清理例程编写为ServletContextListener,则可能会在容器生命周期内多次运行。 (例如,如果在容器进程仍处于运行状态时多次修改并重新加载WAR。)

但是,如果使用Runtime.addShutdownHook实现清理,它将只运行一次:当整个容器的JVM关闭时。

ServletContextListener可能是您的正确答案,因为它将您的清理例程与Web应用程序的生命周期相结合,而不是托管它的容器进程的生命周期。

答案 3 :(得分:2)

我们正在谈论的泄漏只会在我们进行热/部署时发生。但是,如果在每次部署更改后重新启动服务器,则挂钩应该可以正常工作而不会发生内存泄 此外,另一个控制泄漏的因素是您试图通过侦听器/钩子控制的资源清理类型。

答案 4 :(得分:1)

为什么不两个都做?虽然ServletContextListener更适合于webapp,但我发现在开发期间,服务器经常突然停止,然后从不调用contextDestroyed(),因此您可以使用这两种机制来确保始终正常关闭:

实现ServletContextListener,其中contextInitialized调用addShutdownHook()和contextDestroyed调用removeShutdownHook()。 hook和contextDestroyed都可以委托一些内部方法来实际进行清理。

这样,如果正确调用了侦听器,那么钩子就会被添加和删除(但不会被调用)并且没有泄漏,但是如果服务器在没有上下文被破坏的情况下死掉,那么关闭钩子会清除它。