Отладка утечки памяти - org.hibernate.engine.StatefulPersistenceContext

Существует служба, которая подключается к базе данных Oracle для чтения данных и использует Hibernate-3.6 и SpringData-JPA-1.10.x. Часто генерируются дампы кучи, что приводит к нехватке памяти на хостах.

Проанализировав несколько heapdumps с использованием Eclipse MAT, обнаружил, что большая часть памяти накапливается в одном экземпляре org.hibernate.engine.StatefulPersistenceContext -> org.hibernate.util.IdentityMap -> java.util.LinkedHashMap.

введите описание изображения здесь И подозреваемый в утечке говорит

В потоке java.lang.Thread @ 0x84427e10 ...: 29 хранятся локальные переменные с общим размером 1 582 637 976 (95,04%) байтов.

Память накапливается в одном экземпляре "java.util.LinkedHashMap", загруженном "".

Поиск его в Stackru, и он говорит, что SessionFactory должен быть singleton, а session.flush() и session.clear() должны вызываться перед каждым вызовом для очистки кэша. Но SessionFactory явно не инициализируется и не используется в коде.

Что вызывает утечку памяти (похоже, что результат каждого запроса кэшируется, а не очищается) и как это исправить?

Больше информации о конфигурации Spring Data:

TransactionManager инициализируется как:

<tx:annotation-driven mode='proxy' proxy-target-class='true' />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   ....
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" depends-on="...">
   ....
</bean>

Для взаимодействия с таблицей объявляется интерфейс, расширяющий Spring Data Repository и JpaSpecificationExecutor. Оба введены в класс домена, который он будет обрабатывать.

Метод действия API имеет аннотацию @Transactional(propagation = Propagation.SUPPORTS, readOnly = true),

1 ответ

Из того, что вы описываете, я ожидаю продолжения:

Hibernate (на самом деле JPA в целом) сохраняет ссылку на все сущности, которые он загружает или сохраняет на время жизни сеанса.

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

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

  • что-то работает в открытом сеансе все время без его закрытия. Может быть, что-то вроде пакетного задания или запланированного задания, которое выполняется через равные промежутки времени.

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

Чтобы найти виновника, включите ведение журнала для открытия и закрытия сессии. Судя по https://hibernate.atlassian.net/browse/HHH-2425 org.hibernate.impl.SessionImpl должна быть правильная категория журнала, и вам, вероятно, нужна регистрация уровня трассировки.

Теперь протестируйте различные запросы к вашему серверу и посмотрите, есть ли какие-либо сессии, которые открыты, но не закрыты.

Вопрос содержит информацию о создании некоторых бобов. Но проблема не в этом. Проблема в вашем коде, где вы используете эти beans.

Пожалуйста, проверьте свой код. Вероятно, вы загружаете элементы в цикле. И цикл завершается транзакцией.

Hibernate создает огромные промежуточные объекты и не очищает их до завершения транзакции (фиксация / откат).

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