contextDestroyed () против addShutdownHook () - PullRequest
5 голосов
/ 05 августа 2011

В настоящее время я использую ServletContextListener и использую contextDestroyed() для запуска задач очистки в моем веб-приложении перед его закрытием.Тем не менее, я читал о том, как Runtime.addShutdownHook(Thread) может использоваться для той же цели.

Есть ли какая-либо разница между этими двумя методами выполнения очистки перед отключением?Что предпочтительнее для веб-приложения с точки зрения функциональности, эффективности и удобства обслуживания?

Ответы [ 5 ]

8 голосов
/ 05 августа 2011

Я думаю, что ServletContextListener больше подходит для веб-приложения, потому что вы очищаете ресурсы для каждого сеанса.

Отключение выполняется с выключенной JVM. Это будет, когда вы остановите свой контейнер, что является одноразовым событием.

4 голосов
/ 05 августа 2011

Опасность использования addShutdownHook () заключается в том, что вы, скорее всего, получите утечку загрузчика классов, которая станет очевидной при повторном развертывании приложения несколько раз.

Поскольку класс перехватчика завершения работы (либо подкласс Thread, либо реализация Runnable в вашем веб-приложении) поступает из загрузчика классов вашего веб-приложения, даже после того, как ваше веб-приложение будет отменено контейнером, перехватчик завершения все равно будет зарегистрирован в системе. Это означает, что загрузчик классов всего веб-приложения не может быть собран мусором.

Я бы определенно рекомендовал ServletContextListener.

3 голосов
/ 05 августа 2011

Многие контейнеры сервлетов поддерживают операции для динамического удаления и / или перезагрузки WAR-файлов без остановки процесса JVM. Таким образом, если вы напишите свою процедуру очистки как ServletContextListener, она может потенциально выполняться несколько раз в течение срока службы контейнера. (Например, если вы изменили и перезагрузили WAR несколько раз, пока процесс контейнера еще не завершен.)

Однако, если вы реализуете свою очистку с помощью Runtime.addShutdownHook, она будет запускаться только один раз: когда JVM для контейнера в целом выключится.

ServletContextListener, вероятно, является правильным решением для вас, поскольку он связывает вашу процедуру очистки с жизненным циклом веб-приложения, а не с процессом контейнерного процесса, в котором оно размещается.

2 голосов
/ 31 октября 2011

Утечка, о которой мы говорим, произойдет, только если мы сделаем горячее / развертывание.Однако, если сервер перезапускается после каждого изменения развертывания, ловушка должна работать без утечки памяти.Кроме того, еще одним фактором, определяющим утечку, является тип очистки ресурсов, который вы пытаетесь контролировать с помощью слушателя / хука.

1 голос
/ 23 февраля 2017

Почему бы не сделать оба?Хотя ServletContextListener больше подходит для веб-приложения, я обнаружил, что во время разработки сервер часто останавливается внезапно, а затем никогда не вызывается contextDestroyed (), поэтому вы можете использовать оба механизма, чтобы гарантировать, что всегда будет корректное завершение работы:

Реализация ServletContextListener, где contextInitialized вызывает addShutdownHook () и contextDestroyed вызывает removeShutdownHook ().Хук и contextDestroyed могут оба делегировать некоторому внутреннему методу, чтобы фактически выполнить очистку.

Таким образом, если слушатель вызывается должным образом, хук добавляется и удаляется (но не вызывается), и утечка отсутствует.но если сервер умирает без уничтожения контекста, ловушка отключения очищает все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...