“同步”会影响流的内存占用吗?

我们有一个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同步会发生任何变化?

sb3006 回答:“同步”会影响流的内存占用吗?

结果证明,更改为“同步”是一个红鲱鱼,既不是原因,也不是解决方案。

原因是EclipseLink的UnitOfWork,默认情况下,它包含对每个已加载实体的引用。 getInternalMessage()正在加载许多对象时,堆慢慢填充了。解决方案是使用ReferenceMode.FORCE_WEAK,它只会创建对已加载实体的弱引用,从而允许对其进行GC处理。

我猜想使getInternalMessage() 同步会改变执行,从而使对象加载速度变慢,也许会给GC多一点时间。在同一时间段内,这可能会导致内存倾斜速度变慢,但是后来我们发现在同步的情况下,我们也遇到了OOM。

本文链接:https://www.f2er.com/3064307.html

大家都在问