I have a slow memory leak in my Java application. I was wondering if this could be caused by not always closing the Entitymanager when used. However using myeclipse to generate DB code, I'm getting methods like this:
public Meit update(Meit entity) {
logger.info("updating Meit instance");
try {
Meit result = getEntityManager().merge(entity);
logger.info("update successful");
return result;
} catch (RuntimeException re) {
logger.error("update failed");
throw re;
}
}
Which never close the EntityManager. Considering this is generated code, I'm wondering who's right, me or the IDE.
As @Ruggs said if you are managing the EntityManager lifecycle yourself (as opposed to having CMP Container Managed Persistence done by a J2EE) then you need to close the EntityManager yourself or at least call EntityManager.clear()
to detach entities.
EntityManager are lightweight object so there is no need for just having one, you can create one for each transaction and close it after the transaction is committed.
All the entities that load/persist through an EntityManager stay in memory until you explicitly detach the entities from it (via EntityManager.detach()
or EntityManager.clear()
or EntityManager.close()
). So it's better to have short-lived EntityManagers. If you persist 1000000 entities via the same EntityManager without detaching them after you will get a OOME (doesn't matter if you persist each entity in it's own EntityTransaction).
It's all explained in this post http://javanotepad.blogspot.com/2007/06/how-to-close-jpa-entitymanger-in-web.html.
As an example (taken from the earlier post) if you want to avoid "memory leaks" you should do something like this (if you are not using CMP):
EntityManager em = emf.createEntityManager();
try {
EntityTransaction t = em.getTransaction();
try {
t.begin();
// business logic to update the customer
em.merge(cust);
t.commit();
} finally {
if (t.isActive()) t.rollback();
}
} finally {
em.close();
}