Отладка утечки памяти - org.hibernate.engine.StatefulPersistenceContext - PullRequest
0 голосов
/ 12 июня 2018

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

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

enter image description here И подозреваемый в утечке говорит

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

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

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

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

Дополнительная информация о конфигурации данных Spring:

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 Репозиторий и JpaSpecificationExecutor .Оба они введены в класс домена, который он будет обрабатывать.

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

1 Ответ

0 голосов
/ 13 июня 2018

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

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

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

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

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

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

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

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

...