调试内存泄漏 - org.hibernate.engine.StatefulPersistenceContext

时间:2018-06-12 17:20:55

标签: java hibernate memory-leaks spring-data-jpa sessionfactory

有一项服务连接到Oracle DB以读取数据,它使用 Hibernate-3.6 SpringData-JPA-1.10.x 。堆转储频繁生成,导致主机内存不足。

在使用Eclipse MAT分析了几个堆转换后,发现大部分内存都累积在 org.hibernate.engine.StatefulPersistenceContext - >的一个实例中。 org.hibernate.util.IdentityMap - > java.util.LinkedHashMap中

enter image description here 泄漏嫌疑人说

  

线程java.lang.Thread @ 0x84427e10 ...:29保持本地   总大小为1,582,637,976(95.04%)字节的变量。

     

内存累积在“java.util.LinkedHashMap”的一个实例中   由“”加载。

在StackOverflow上搜索它,它说SessionFactory应该是singleton,session.flush()和session.clear()应该在每次调用之前调用以清除缓存。但 SessionFactory未在代码中显式初始化或使用。

导致内存泄漏的原因(看起来每个查询的结果都被缓存但未清除)以及如何修复它?

有关Spring Data配置的更多信息:

TransactionManager初始化为:

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

要与表进行交互,会声明一个接口,扩展Spring Data 存储库 JpaSpecificationExecutor 。两者都输入到它将处理的域类中。

API活动方法具有注释@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)

2 个答案:

答案 0 :(得分:0)

根据您的描述,这是我期待的:

Hibernate(通常是JPA)保持对它加载或保存的所有实体的引用,以用于会话的生命周期。

在典型的Web应用程序设置中,这不是问题,因为。新会话从每个请求开始,并在请求完成后关闭,并且它不涉及那么多实体。

但是对于您的应用程序来说,会话​​似乎不断增长和发展。 我可以想象以下原因:

  • 某些东西在开放的会话中一直运行而没有关闭。可能是批处理作业或定期运行的预定作业。

  • Hibernate的配置方式使得它可以重用相同的会话而无需关闭它。

为了找到罪魁祸首启用日志记录以打开和关闭会话。从https://hibernate.atlassian.net/browse/HHH-2425 countif判断应该是正确的日志类别,您可能需要跟踪级别日志记录。

现在测试对您的服务器的各种请求,看看是否有任何会话被打开但未关闭。

答案 1 :(得分:0)

该问题包含有关某些bean的创建的信息。但是问题不在于此。问题出在您的代码中,您在哪里使用这些bean。

请检查您的代码。可能是您正在循环加载项目。循环包裹着事务。

Hibernate创建了巨大的中间对象,并且在事务完成(提交/回滚)之前不会清理它们。