使用重播(selectorFoo)但不发布(selectorFoo)时的OOM

时间:2019-01-15 00:34:59

标签: java rx-java2 project-reactor

这因OOM而崩溃:

Flowable.range(1, 5000)
        .map(__ -> new byte[1024 * 1024])
        .replay(
          fb ->
            fb.take(1)
              .concatMap(__ -> fb)
          ,1
        )
        .count()
        .toFlowable()
        .blockingSubscribe(c -> System.out.println("args = [" + c + "]"));

我认为这是因为replay一直在保持上游的排放,尽管我本以为1缓冲区sizse提示将使其不……。失踪了吗?

这不会崩溃:

Flowable.range(1, 5000)
        .map(__ -> new byte[1024 * 1024])
        .publish(
          fb ->
            fb.take(1)
              .concatMap(first -> fb.startWith(first))
          ,1
        )
        .count()
        .toFlowable()
        .blockingSubscribe(c -> System.out.println("args = [" + c + "]"));

但是我不确定是否能保证像这样从上游获得所有排放物...

1 个答案:

答案 0 :(得分:1)

我已经对此进行了调查,并发现了问题的原因:RxJava 2中replay中的错误。

发生的情况是,replay在本地变量中拥有对两个订户的引用,一个为take的引用,另一个为concatMap的内部使用者的引用,因此有一个GC根从主线程到已终止的take仍然引用第一项。由于有界重放使用链表,因此该第一项将继续通过其“下一个”链接引用更新的项目,并最终耗尽内存。

publish不会保留对旧值的引用,因此这不是问题。