我的Java应用程序中的内存泄漏很慢。我想知道这是否可能是由于在使用时并不总是关闭Entitymanager。但是使用myeclipse生成数据库代码,我得到的方法是这样的:
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;
}
}
永远不会关闭EntityManager。考虑到这是生成的代码,我想知道谁是对的,我还是IDE。
答案 0 :(得分:6)
正如@Ruggs所说,如果您自己管理EntityManager生命周期(而不是由J2EE完成CMP容器管理持久性),那么您需要自己关闭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();
}
答案 1 :(得分:1)
实体经理通常应该与应用程序具有相同的生命周期,而不是基于每个请求创建或销毁。
你的“内存泄漏”可能只是JPA正在进行的缓存。您没有说明您使用的是哪个JPA提供程序,但我从经验中知道,默认情况下EclipseLink会进行大量缓存(这是JPA和ORM所谓的优势的一部分)。
你怎么知道你有内存泄漏?
答案 2 :(得分:1)
答案 3 :(得分:1)
听起来您正在使用应用程序管理的EntityManager。您需要自己调用EntityManager,这是规范的一部分。关闭webapp时,还需要关闭EntityManagerFactory。
我建议使用OpenEJB或Springframework之类的东西为你管理EntityManager / EntityMangerFactory。