有一项服务连接到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应该是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)
。
答案 0 :(得分:0)
根据您的描述,这是我期待的:
Hibernate(通常是JPA)保持对它加载或保存的所有实体的引用,以用于会话的生命周期。
在典型的Web应用程序设置中,这不是问题,因为。新会话从每个请求开始,并在请求完成后关闭,并且它不涉及那么多实体。
但是对于您的应用程序来说,会话似乎不断增长和发展。 我可以想象以下原因:
某些东西在开放的会话中一直运行而没有关闭。可能是批处理作业或定期运行的预定作业。
Hibernate的配置方式使得它可以重用相同的会话而无需关闭它。
为了找到罪魁祸首启用日志记录以打开和关闭会话。从https://hibernate.atlassian.net/browse/HHH-2425 countif
判断应该是正确的日志类别,您可能需要跟踪级别日志记录。
现在测试对您的服务器的各种请求,看看是否有任何会话被打开但未关闭。
答案 1 :(得分:0)
该问题包含有关某些bean的创建的信息。但是问题不在于此。问题出在您的代码中,您在哪里使用这些bean。
请检查您的代码。可能是您正在循环加载项目。循环包裹着事务。
Hibernate创建了巨大的中间对象,并且在事务完成(提交/回滚)之前不会清理它们。