Recibo diariamente errores de OutOfMemory en una nueva versión de mi aplicación. Tenemos 1,5 GB de almacenamiento asignado para Tomcat.JPA Hibernate DBCP Tomcat OutOfMemory
Utilizando el analizador de memoria Eclipse (http://www.eclipse.org/mat/) que tiene la siguiente debajo de la ruta más corta Acumulación
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
inspección más a fondo de esta muestra una gran cantidad de cadenas duplicadas que son consultas Hibernate. En la pantalla de inicio de mi aplicación, cargo una lista de documentos. Existe un duplicado de la consulta 8,241 veces en el volcado de pila.
También noté que 1 GB del montón está contenido en org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool. Esta consulta de documento estaba cargando los datos binarios del documento. El documento que está cargando es de alrededor de 1 MB. Esto me hace sospechar que la Lista no está siendo limpiada por el recolector de basura. Eliminaremos datos innecesarios de la consulta, pero todavía me preocupa que los objetos se queden.
Estoy usando JPA, Hibernate y Spring. Estoy usando @Transactional(readOnly=true)
en el método que obtiene la lista de documentos. Aquí está mi configuración Spring para la fuente de datos:
<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>
Estoy utilizando Tomcat para proporcionar la agrupación de conexiones. Aquí está mi configuración:
<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"/>
La capa de servicio tiene @Transactional. Mi APP de consulta es el siguiente:
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;
}
¿Qué debería estar buscando para ayudar a identificar la causa de la pérdida de memoria? ¿Hay alguna configuración de DBCP, Hibernate o Spring que pueda estar contribuyendo a esto? ¿Hay algo que notes en el código de consulta JPA que podría estar contribuyendo?
¿Cómo se implementa getEntityManager()? ¿se inyectó EntityManager con la anotación @PersistenceContext? – samlewis
Sí. Spring está inyectando, esto no se está ejecutando en un servidor JavaEE. Estamos usando Tomcat. – Allan