Куча заполнена com.mysql.jdbc.JDBC4Connection

Я анализирую дамп кучи, где у меня 50% live set в куче. Это вызвано тем, что большой объем кучи зарезервирован только для хранения всего JDBC4Connection и его хэш-карты внутренних свойств. Это куча приложения, работающего пару дней.

Куча заполнена com.mysql.jdbc.JDBC4Connection

Похоже, что он содержит тысячи объектов подключения JDBC и его конфигурацию.

Куча заполнена com.mysql.jdbc.JDBC4Connection

Я нашел вопрос, который задавал аналогичный вопрос, но был отклонен, предполагая, что пользователь не закрывает соединения: Слишком много экземпляров com.mysql.jdbc.JDBC4Connection.

Однако я использую org.springframework.data.jpa.repository.JpaSpecificationExecutor.findAll, не запрашивая напрямую базу данных. Код:

Specification<AccountProfile> spec = getUserInfoListSurfacing(userInfo);
JPAImpl.findAll(spec, new PageRequest(0, 1, Sort.Direction.DESC, "reportedDate")).getContent()

Вот определение bean-компонента для этого пула соединений

<bean id = "db" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name = "dataSourceName" value = "users"/>
        <property name = "driverClass" value = "${userdb.driver}"/>
        <property name = "forceUseNamedDriverClass" value = "true"/>
        <property name = "jdbcUrl" value = "${userdb.url}"/>
        <property name = "user" value = "${userdb.username}"/>
        <property name = "password" value = "${userdb.password}"/>
        <property name = "initialPoolSize" value = "${userdb.hibernate.c3p0.initialPoolSize}"/>
        <property name = "maxPoolSize" value = "${userdb.hibernate.c3p0.max_size}"/>
        <property name = "minPoolSize" value = "${userdb.hibernate.c3p0.min_size}"/>
        <property name = "idleConnectionTestPeriod" value = "${userdb.hibernate.c3p0.idle_test_period}"/>
        <property name = "maxStatements" value = "${userdb.hibernate.c3p0.max_statements}"/>
        <property name = "maxIdleTime" value = "${userdb.hibernate.c3p0.idle_test_period}"/>
        <property name = "preferredTestQuery" value = "${userdb.hibernate.c3p0.validationQuery}"/>
        <property name = "testConnectionOnCheckout" value = "${userdb.hibernate.c3p0.testOnBorrow}"/>
        <property name = "acquireIncrement" value = "${userdb.hibernate.c3p0.acquireincrement}"/>
        <property name = "unreturnedConnectionTimeout"
                  value = "${userdb.hibernate.c3p0.unreturnedConnectionTimeout}"/>
        <property name = "debugUnreturnedConnectionStackTraces" value = "${userdb.hibernate.c3p0.debugUnreturnedConnectionStackTraces}"/>
        <property name = "maxConnectionAge" value = "${userdb.hibernate.c3p0.maxconnectionage}"/>
        <property name = "numHelperThreads" value = "${userdb.hibernate.c3p0.numHelperThreads}"/>
        <property name = "connectionCustomizerClassName" value = "${userdb.hibernate.c3p0.connectionCustomizerClassName}"/>
    </bean>

Мне не удалось найти подтвержденных отчетов об утечках памяти в версиях Hibernate, которые я использую.

Я использую spring-data-jpa версии 2.0.6. Final hibernate-core версия 4.3.5.Финал hibernate-jpa-2.1-api версия 1.0.2.Final

c3p0 создает пул подключений к базе данных. Неудивительно, что вы видите много объектов связи.

Sazzadur Rahaman 18.07.2018 22:46

@SazzadurRahaman Создает пул из 200 подключений, а не из 45 тысяч. Ожидается, что соединение JDBC не будет использоваться после того, как оно будет удалено пулом.

stan 18.07.2018 22:50

Я понимаю вашу точку зрения.

Sazzadur Rahaman 18.07.2018 22:51

Вы создаете новые контексты приложения для установления соединения? (То есть вы делаете что-то вроде new ClassPathXmlApplicationContext в своем коде? Рядом с этим вы, вероятно, загружаете все свое приложение дважды (покажите свой web.xml), и вам действительно нужно 200 подключений? Наконец, я предлагаю отказаться от C3P0 и заменить его на HikariCP (C3P0 isn больше не поддерживается).

M. Deinum 19.07.2018 07:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
367
1

Ответы 1

Вы показываете 224 экземпляра объекта «управляемый». На каждый пул соединений приходится один экземпляр «управляемого», поэтому у вас есть 224 пула соединений, содержащих ссылки на соединения, а не только один. Вы должны понимать, почему вы создаете так много пулов, когда типичному приложению нужен только один.

Обычная ошибка, которая может вызвать это, - создавать новый пул соединений каждый раз, когда вы хотите установить новое соединение. Менее распространенной причиной является использование одного и того же источника данных для установления соединений при нескольких аутентификациях с использованием dataSource.getConnection (пользователь, пароль). Новый пул соединений устанавливается для каждой отдельной аутентификации.

Поскольку вы не создаете экземпляр пула подключений напрямую, а используете для этого Spring, не так просто отладить, почему вы создаете экземпляр пула. Одна вещь, которую вы обязательно должны добавить, - это атрибут destroy-method в ваш XML-тег bean. Это...

<bean id = "db" class = "com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method = "close">
   ...
</bean>

Вы можете генерировать все эти пулы, просто повторно развертывая приложение в горячем режиме, и не очищая старые пулы, потому что Spring не знает, что он должен очищать ваши bean-компоненты. См. Spring Обратные вызовы разрушения.

Метод close автоматически определяется как метод уничтожения (начиная с Spring 3.2). Так что в зависимости от версии, которая может не понадобиться.

M. Deinum 19.07.2018 07:53

Другие вопросы по теме