java - “同步”会影响流的内存占用吗?
问题描述
我们有一个奇怪的 OutOfMemory(堆)案例。鉴于这种方法
private void processRemainingIds(final ITransaction tx) {
remainingIds.stream()//
.map(this::getInternalMessage)//
.filter(this::isMessageNeedsProcessing)//
.forEach(msg -> registerMessageAsMissing(msg, tx));
}
如果剩余Ids 足够大,则此方法会相当稳定地填满堆。
getInternalMessage
将加载“正常”大小的数据模型结构(即没有 blob / clob 等,只有几十个字符串和数字)registerMessageAsMissing
内部调用同步方法(也许这是相关的)- 使
getInternalMessage
“同步”完全改变了内存行为,堆大小不再增加
我希望上述实现会创建大量内部消息,检查并在需要时处理它们,然后丢弃每个对象并偶尔运行 GC。但这不是我们所看到的,而是我们得到
OOM的标准问题,即。“有东西抓住了你的物体”我很熟悉。但是为什么getInternalMessage
同步会改变任何东西呢?
解决方案
事实证明,更改为“同步”是一条红鲱鱼,既不是原因也不是解决方案。
原因是 EclipseLink 的 UnitOfWork,默认情况下它包含对每个加载实体的引用。由于getInternalMessage()
加载了许多对象,堆慢慢填满。解决方案是使用ReferenceMode.FORCE_WEAK
,它只创建对加载实体的弱引用,因此允许它们被 GC'ed。
我推测使getInternalMessage()
同步改变了执行,使得对象加载速度变慢,可能会给 GC 更多时间。这可能导致在同一时间段内的内存倾斜速度较慢,但我们后来发现使用同步也遇到了 OOM。
推荐阅读
- python - 修改覆盖 matplotlib 的轴和标签
- github - 如何在自定义域中/之后命名存储库?
- c# - 实体框架添加具有相关子项的新项
- javascript - 在应用程序启动时启动 Bull Queue 进程
- google-drive-api - 谷歌计算实例和谷歌驱动器之间的谷歌驱动器api
- tensorflow - 在 tensorflow 版本 1.14 和 2.0 上训练 TensorFlow 对象检测模型时出错
- powershell - PowerShell获取文件夹中没有路径和tsv行数的文件名
- python - 在 Django admin TabularInline 中替换“添加另一行”按钮的 href
- angular - ctx。在 Angular 中未定义
- reactjs - 两次通过数组的简单反应错误映射