Otrzymuję codzienne błędy OutOfMemory w nowej wersji mojej aplikacji. Mamy 1,5 GB sterty przydzielonej dla Tomcat.JPA Hibernate DBCP Tomcat OutOfMemory
Korzystanie z pamięci analizatora Eclipse (http://www.eclipse.org/mat/) Mam następujący pod najkrótszej drodze akumulacji
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
Ponadto kontrola ta pokazuje wiele zduplikowanych ciągów, które Hibernate zapytaniami. Na ekranie głównym aplikacji ładuję listę dokumentów. Duplikat zapytania istnieje 8 241 razy w zrzucie sterty.
Zauważyłem również, że 1 GB sterty jest zawarte w org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool. To zapytanie do dokumentu ładowało dane binarne dokumentu. Obciążany dokument wynosi około 1 MB. To sprawia, że podejrzewam, że lista nie jest czyszczona przez garbage collectora. Usuniemy niepotrzebne dane z zapytania, ale nadal mnie niepokoją, że obiekty się kręcą.
Używam JPA, hibernacji i wiosny. Używam @Transactional(readOnly=true)
w metodzie, która pobiera listę dokumentów. Oto moja konfiguracja Spring dla źródła danych:
<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>
Używam Tomcat do zapewnienia połączenia puli. Oto moja konfiguracja:
<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"/>
Warstwa usług ma wartość @Transactional. Moja zapytań JPA wygląda następująco:
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;
}
Co należy szukać, aby pomóc zidentyfikować przyczynę wycieku pamięci? Czy są jakieś ustawienia DBCP, Hibernate lub Spring, które mogą się do tego przyczynić? Czy jest coś, co można zauważyć w kodzie zapytań WZP, który może się przyczyniać?
W jaki sposób implementuje się getEntityManager()? czy EntityManager został wprowadzony z adnotacją @PersistenceContext? – samlewis
Tak. Wiosna wstrzykuje, to nie działa na serwerze JavaEE. Używamy Tomcat. – Allan