Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entitymanager causing memory leak?

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.

like image 571
GBa Avatar asked Apr 01 '09 16:04

GBa


2 Answers

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();
}
like image 67
RubenLaguna Avatar answered Sep 23 '22 22:09

RubenLaguna


Entity managers should generally have the same lifecycle as the application and not be created or destroyed on a per-request basis.

Your "memory leak" may be nothing more than the caching JPA is doing. You don't say which JPA provider you use but I know from experience that EclipseLink by default does extensive caching (which is part of the alleged benefits of JPA and ORM in general).

How do you know you have a memory leak?

like image 30
cletus Avatar answered Sep 21 '22 22:09

cletus