java - 调试内存泄漏 - org.hibernate.engine.StatefulPersistenceContext
问题描述
有一个服务连接到 Oracle DB 以读取数据,它使用Hibernate-3.6和SpringData-JPA-1.10.x。堆转储频繁生成,导致主机内存不足。
在使用 Eclipse MAT 分析了几个 heapdump 之后,发现大部分内存是在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>
为了与表交互,声明了一个扩展 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
判断应该是正确的日志类别,您可能需要跟踪级别的日志记录。
现在测试对服务器的各种请求,看看是否有任何会话打开但未关闭。
推荐阅读
- java - 通过用户输入改变 Setter 和 Getter
- python - 如何使用正则表达式替换 Python 中 dict 的内容
- javascript - PropTypes 不是必需的,但在 VSCode 中按要求显示
- ruby-on-rails - Chat belongs_to 两个 User 实例和 User has_many :chats (ruby on rails )
- javascript - GAS UrlFetchApp.fetchAll 将所有响应合并到一个 JSON 响应中
- react-native - FlatList 中的 React Native 滑动项与 TouchableOpacity 的 onPress 冲突
- node.js - Gastby 停止在本地为特定操作提供站点服务
- scikit-learn - MLflow 网络服务器返回 400 状态,“列 X 的输入类型不兼容。无法安全地将 float64 转换为
我正在使用
MLflow
and实现异常检测 Web 服务sklearn.pipeline.Pipeline()
。该模型的目的是使用服务器日志检测网络爬虫,而response_length
列是我的功能之一。在服务模型之后,为了测试 Web 服务,我发送了下面的请求- javascript - 如何检测匹配和捕获的正则表达式未找到匹配项
- node.js - CastError:模型“collection”的路径“_id”处的值“60f0d02f36ee6f2e505369e8”(类型字符串)转换为 ObjectId 失败