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

Sar*_*nan 5 java memory-leaks hibernate sessionfactory spring-data-jpa

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

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

在此输入图像描述 泄密嫌疑人说

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

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

在 StackOverflow 上搜索它,它说 SessionFactory 应该是单例的,并且在每次调用清除缓存之前应该调用 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>
Run Code Online (Sandbox Code Playgroud)

为了与表交互,声明了一个扩展 Spring Data RepositoryJpaSpecificationExecutor的接口。两者都被输入到它将处理的域类中。

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

Jen*_*der 4

根据您的描述,我预计会发生这样的情况:

Hibernate(实际上是一般的 JPA)在会话生命周期内保留对其加载或保存的所有实体的引用。

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

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

  • 某些东西始终在开放会话中运行,而不会关闭。也许是批处理作业或定期运行的计划作业。

  • Hibernate 的配置方式是重用同一个会话而不关闭它。

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

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