Sar*_*nan 5 java memory-leaks hibernate sessionfactory spring-data-jpa
有一个服务连接到 Oracle DB 来读取数据,它使用Hibernate-3.6和SpringData-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 Repository和JpaSpecificationExecutor的接口。两者都被输入到它将处理的域类中。
API活动方法有注释@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)。
根据您的描述,我预计会发生这样的情况:
Hibernate(实际上是一般的 JPA)在会话生命周期内保留对其加载或保存的所有实体的引用。
在典型的 Web 应用程序设置中,这不是问题,因为。每个请求都会启动一个新会话,并在请求完成后关闭,并且它不涉及那么多实体。
但对于您的应用程序来说,会话似乎不断增长。我可以想象以下原因:
某些东西始终在开放会话中运行,而不会关闭。也许是批处理作业或定期运行的计划作业。
Hibernate 的配置方式是重用同一个会话而不关闭它。
为了找到罪魁祸首,请启用打开和关闭会话的日志记录。从https://hibernate.atlassian.net/browse/HHH-2425 来看org.hibernate.impl.SessionImpl应该是正确的日志类别,并且您可能需要跟踪级别日志记录。
现在测试对服务器的各种请求,看看是否有任何会话已打开但未关闭。
| 归档时间: |
|
| 查看次数: |
7987 次 |
| 最近记录: |