11

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.

4

4 回答 4

6

正如@Ruggs 所说,如果您自己管理 EntityManager 生命周期(而不是由 J2EE 完成 CMP Container Managed Persistence),那么您需要自己关闭 EntityManager 或至少调用EntityManager.clear()分离实体。

EntityManager 是轻量级对象,因此不需要一个,您可以为每个事务创建一个,并在事务提交后关闭它。

通过 EntityManager 加载/持久的所有实体都保留在内存中,直到您显式地从它分离实体(通过EntityManager.detach()EntityManager.clear()EntityManager.close())。所以最好有短命的EntityManagers。如果您在获得 OOME 后通过同一个 EntityManager 保留 1000000 个实体而不分离它们(是否将每个实体保留在它自己的 EntityTransaction 中并不重要)。

这一切都在这篇文章http://javanotepad.blogspot.com/2007/06/how-to-close-jpa-entitymanger-in-web.html中进行了解释。

作为一个例子(取自之前的帖子),如果你想避免“内存泄漏”,你应该做这样的事情(如果你不使用 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();
}
于 2010-02-12T18:37:05.157 回答
1

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?

于 2009-04-01T16:08:28.820 回答
1

听起来您正在使用应用程序管理的 EntityManager。您需要自己调用 close EntityManager,这是规范的一部分。关闭 web 应用程序时,您还需要关闭 EntityManagerFactory。

我建议使用 OpenEJB 或 Springframework 之类的东西来为您管理 EntityManager/EntityMangerFactory。

于 2009-04-01T16:35:00.193 回答
1

检查是否真的泄漏

如果是这样,请获取Eclipse 内存分析器并对其进行分析。

这里的博客文章也可能有用。

于 2009-04-01T16:29:27.960 回答