Saravanan
Saravanan

Reputation: 654

Debugging Memory leak - org.hibernate.engine.StatefulPersistenceContext

There is a service that connects to Oracle DB for reading data and it uses Hibernate-3.6 and SpringData-JPA-1.10.x. Heap dumps are getting generated frequently which results in out of memory on the hosts.

After analyzing few heapdumps using Eclipse MAT, found that the majority of the memory is accumulated in one instance of org.hibernate.engine.StatefulPersistenceContext -> org.hibernate.util.IdentityMap -> java.util.LinkedHashMap.

enter image description here And the leak suspect says

The thread java.lang.Thread @ 0x84427e10 ... : 29 keeps local variables with total size 1,582,637,976 (95.04%) bytes.

The memory is accumulated in one instance of "java.util.LinkedHashMap" loaded by "".

Searched it on StackOverflow and it says SessionFactory should be singleton and session.flush() and session.clear() should be invoked before each call to clear the cache. But SessionFactory is not explicitly initialized or used in the code.

What's causing the memory leak here (looks like the result of each query is cached and not cleared) and how to fix it?

More info about the Spring Data configuration:

TransactionManager is initialized as:

<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>

To interact with the table, an interface is declared extending Spring Data Repository and JpaSpecificationExecutor. Both are typed into the domain class that it will handle.

API activity method has the annotation @Transactional(propagation = Propagation.SUPPORTS, readOnly = true).

Upvotes: 5

Views: 8839

Answers (2)

misbah
misbah

Reputation: 189

The question contains information about the creations of some beans. But the problem doesn't lie there. The problem is in your code, where have you use these beans.

Please check your code. Probably you are loading items in a loop. And the loop is wrapped with a transaction.

Hibernate creates huge intermediate objects, and it doesn't clean these before the transaction being completed (commit/rollback).

Upvotes: 0

Jens Schauder
Jens Schauder

Reputation: 81907

From what you describe this is what I expect to be going on:

Hibernate (actually JPA in general) keeps a reference to all entities it loads or saves for the lifetime of the session.

In a typical web application setup, this isn't a problem, because. A new session starts with each request and gets closed once the request is finished and it doesn't involve that many entities.

But for your application, it looks like the session keeps growing and growing. I can imagine the following reasons:

  • something runs in an open session all the time without it ever closing. Maybe something like a batch job or a scheduled job which runs at regular intervals.

  • Hibernate is configured in such a way that it reuses the same session without ever closing it.

In order to find the culprit enable logging for opening and closing the session. Judging from https://hibernate.atlassian.net/browse/HHH-2425 org.hibernate.impl.SessionImpl should be the right log category and you probably need trace level logging.

Now test the various requests to your server and see if there are any sessions that get opened but not closed.

Upvotes: 4

Related Questions