Утечка памяти WebappClassLoader и Hibernate при отмене развертывания?

#java #tomcat #memory-leaks

#java #tomcat #утечки памяти

Вопрос:

РЕДАКТИРОВАТЬ: Тема форума Hibernate по этой проблеме:https://forum.hibernate.org/viewtopic.php?f=1amp;t=1035073

Я использую hibernate-4.3.1 , ehcache-core-2.6.7 c3p0-0.9.5-pre5 наряду с Tomcat 7.0.27 , и я испытываю большую утечку PermGen при отключении приложения.

Я выяснил, что существует множество классов, закрепленных с помощью WebappClassLoader (вот список, как показывает JProfiler. Первое число — это количество объектов этого класса в памяти)

Вот код в ContextListener.contextDestroyed() :

 @Override
public void contextDestroyed(ServletContextEvent event) {
    Debug.log.info("SERVER UNDEPLOY:");
    serviceManager.destroyServices();
    serviceManager = null; // this is static field :(

    for (Object o : C3P0Registry.getPooledDataSources()) {
        PooledDataSource dataSource = (PooledDataSource) o;
        try {
            Debug.log.info(String.format(
                    "-> deregistering C3P0 pool: size %s",
                    dataSource.getThreadPoolSize()));
            dataSource.close();
            Thread.sleep(500);
        } catch (SQLException e) {
            Debug.log.error(String.format(
                    "   FAILED deregistering C3P0 pool: %s",
                    dataSource.getDataSourceName()), e);
        } catch (InterruptedException e) {
        }
    }

    Debug.log.info("-> shutting down cache manager");
    CacheManager.getInstance().shutdown();

    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        try {
            Debug.log.info(String.format(
                    "-> deregistering jdbc driver: %s", driver));
            DriverManager.deregisterDriver(driver);
        } catch (SQLException e) {
            Debug.log.error(String.format(
                    "   FAILED deregistering driver %s", driver), e);
        }
    }

    Debug.log.info("-> shutting down Hibernate factories");
    Hibernate.factory.close(); //SessionFactory
    Hibernate.factory = null; // static field :(

    Debug.log.info("-> stopping logger");
    Debug.log.info("............  SERVER stop ...................");
    ((LoggerContext) LoggerFactory.getILoggerFactory()).stop();

}
  

Я пытался проанализировать корни объектов GC в профилировщике, но безуспешно. Кто-нибудь может подсказать, почему это может быть?

Комментарии:

1. Вы прошли через MemoryLeakProtection Tomcat? Подробнее @ wiki.apache.org/tomcat/MemoryLeakProtection

2. ДА. Рассматриваемый код отменяет регистрацию драйвера JDBC, и я уже знаю о статических переменных и о том, как они могут что-то хранить. Мое приложение само не создает потоки и не работает с загрузчиками классов.

Ответ №1:

я рад, что вы закрываете () свои источники данных contextDestroyed(...) !

Но вы также можете попробовать две новые настройки в c3p0, предназначенные специально для решения проблем с утечкой памяти в Tomcat и других средах с горячим повторным развертыванием на основе ClassLoader. Пожалуйста, посмотрите на зеленое поле здесь и ссылки оттуда.

(и, пожалуйста, обновите до последней версии, 0.9.5-pre8. это новые функции, и я не помню, в какой предварительной версии 0.9.5 они появились.)

Комментарии:

1. Я вообще удалил зависимость c3p0, и утечки все еще существуют. «Зеленый ящик» был изучен снова и не помог. Я создал тему гибернации для такого рода утечек: forum.hibernate.org/viewtopic.php?f=1amp;t=1035073