Отладка утечки памяти - 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 создает огромные промежуточные объекты и не очищает их до завершения транзакции (фиксация / откат).