Я получаю ежедневные ошибки OutOfMemory в новой версии моего приложения. У нас есть 1.5 ГБ кучи, выделенной для Tomcat.JPA Hibernate DBCP Tomcat OutOfMemory
Использование анализатора памяти Eclipse (http://www.eclipse.org/mat/) я получил следующее по кратчайшего пути накопления
org.apache.tomcat.dbcp.pool.impl.CursorableLinkedList$Listable @ 0xa1566cc8
_head org.apache.tomcat.dbcp.pool.impl.CursorableLinkedList @ 0xa1566ca8
_pool org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool @ 0xa1566c38
connectionPool org.apache.tomcat.dbcp.dbcp.BasicDataSource @ 0xa1566980
dataSource org.springframework.orm.jpa.JpaTransactionManager @ 0xa0b01760
<Java Local> java.lang.Thread @ 0xa4005900 ajp-8141-5 Thread
Дальнейшее обследование это показывает много повторяющихся строк, которые Hibernate запросы. На главном экране моих приложений загружаю список документов. Дубликат запроса существует 8,241 раз в дампе кучи.
Я также заметил, что 1 ГБ кучи содержится в org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool. Этот запрос документа загружал двоичные данные документа. Документ, который загружается, составляет около 1 МБ. Это заставляет меня подозревать, что список не очищается сборщиком мусора. Мы удалим ненужные данные из запроса, но мне все же приходится беспокоиться о том, что объекты торчат.
Я использую JPA, Hibernate и Spring. Я использую @Transactional(readOnly=true)
по методу, который получает список документов. Вот моя конфигурация Spring для источника данных:
<jee:jndi-lookup jndi-name="jdbc/MyDB" id="myDataSource"/>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="persistenceUnitName" value="WebPU"/>
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
Я использую Tomcat для обеспечения объединения пулов. Вот моя конфигурация:
<Resource auth="Container" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" initialSize="20"
logAbandoned="true" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/MyDB" password="pass" poolPreparedStatements="true" removeAbandoned="true" removeAbandonedTimeout="30"
type="javax.sql.DataSource"
url="jdbc:sqlserver://devmssql;databaseName=MY_DEV;responseBuffering=adaptive;port=1444"
username="user"/>
Сервисный уровень имеет @Transactional. Мой JPA запросы выглядят следующим образом:
public List<Document> getDocs(int cId, int lId, int ldId) {
CriteriaBuilder queryBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Document> select = queryBuilder.createQuery(Document.class);
Root<Document> from = select.from(Document.class);
select.where(
queryBuilder.and(queryBuilder.equal(from.get(Document_.cId), cId),
queryBuilder.equal(from.get(Document_.lId), lId),
queryBuilder.equal(from.get(Document_.ldId), ldId)));
TypedQuery<Document> tq = getEntityManager().createQuery(select);
final List<Document> rl = tq.getResultList();
return rl;
}
Что я должен искать для того чтобы помочь определить причину утечки памяти? Существуют ли какие-либо настройки DBCP, Hibernate или Spring, которые могут способствовать этому? Есть ли что-нибудь, что вы заметили в коде запроса JPA, который может внести вклад?
Как реализован метод getEntityManager()? является EntityManager, введенный аннотацией @PersistenceContext? – samlewis
Да. Spring впрыскивает, это не работает на сервере JavaEE. Мы используем Tomcat. – Allan