Есть ли способ избежать утечек памяти undeployment в Tomcat?

Этот вопрос предназначен для тех, кто когда-либо тестировал кнопку "Найти утечки" в менеджере Tomcat и получил некоторые результаты следующим образом:

Следующие веб-приложения были остановлены (перезагружены, не развернуты), но их классы из предыдущих запусков по-прежнему загружаются в память, что вызывает утечку памяти (используйте профайлер для подтверждения):
/Негерметичное-приложение-имя

Я предполагаю, что это имеет какое-то отношение к этой ошибке "Perm Gen space", которую вы часто получаете с частыми перераспределениями.

Итак, то, что я вижу в jconsole при развертывании, - это то, что мои загруженные классы идут от примерно 2k до 5k. Тогда вы думаете, что undeployment должно отбросить их обратно до 2k, но они останутся на уровне 5k.

Я также попытался использовать следующие параметры JVM:

-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled

Я видел ОЧЕНЬ незначительные провалы в количестве используемого пространства Перми, но не то, что я ожидал, и количество загруженных классов не уменьшалось.

Итак, есть способ настроить Tomcat или создать приложение для более быстрого разгрузки при развертывании? Или мы застряли в перезагрузке сервера после некоторых крупных сеансов отладки?

Выход версии Tomcat:

Версия сервера: Apache Tomcat/6.0.29
Сервер построен: 19 июля 2010 г. 1458
Номер сервера: 6.0.0.29
Название ОС: Windows 7
Версия ОС: 6.1
Архитектура: x86
Версия JVM: 1.6.0_18-b07
JVM Vendor: Sun Microsystems Inc.

Update:

Благодаря ответу celias я решил сделать немного больше копания, и я думаю, что я определил виновника в моем приложении благодаря CXF, Spring и JAXB.

После того, как я узнал, как профилировать приложение Java, я указал профилировщик Tomcat и взял кучи дампов и снимки кучи, чтобы увидеть, как выглядели объекты и классы в памяти. Я обнаружил, что некоторые из перечислений из моей XML-схемы, используемой в моих сгенерированных классах CXF/JAXB (wsdl2java), сохранялись после развертывания. Согласно моему дампу кучи, похоже, что объекты были привязаны к карте. Отказ от ответственности: я признаю, что я все еще немного зеленый с профилированием, и отслеживание дерева вызовов объектов может быть сложным в Java.

Также я должен упомянуть, что я даже не вызывал эту службу, а просто развернул ее, а затем не развернул ее. Похоже, что сами объекты загружались через отражение, начатое с Spring при развертывании. Я полагаю, что я выполнил соглашение о настройке службы CXF в Spring. Поэтому я не уверен на 100%, если это Spring/CXF, JAXB или ошибка отражения.

В качестве побочного примечания: рассматриваемое приложение представляет собой веб-службу с использованием Spring/CXF, а XML - довольно сложная схема (расширение NIEM).

Ответы

Ответ 1

Если вы хотите убедиться, что не вызывают утечек, вам необходимо сделать следующее:

  • Убедитесь, что ваше веб-приложение не использует классы java, которые находятся в общих библиотеках веб-контейнеров. Если у вас есть общие библиотеки, убедитесь, что нет сильных ссылок на объекты в этих библиотеках.
  • Избегайте использования статических переменных, особенно на Java-объектах, таких как HashTable, Sets и т.д. Если вам нужно, убедитесь, что вы вызываете remove, чтобы освободить объекты с помощью карт, списков...

Вот также хорошая статья о ThreadLocal и MemoryLeaks - http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited/

Ответ 2

Tomcat 7 должен внести улучшения в эту область. См. Особенности Apache Tomcat 7, раздел "Больше никаких утечек"

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

Кроме этого, я могу просто сказать, что я сделал тот же опыт и не нашел решения. Обычно развертывание требует перезапуска Tomcat. Я не знаю, кто такой виновник: мое веб-приложение, Tomcat, Hibernate, Гобелен или несколько из них.