2.x: BoundedReplayBuffer temporarily leaks memory · Issue #6475 · ReactiveX/RxJava (original) (raw)

When using Observable.replay(N), the BoundedReplayBuffer keeps up to N+1 items in its buffer. When using replay(1) for example, it keeps a reference to the most recent item, but also the previous, stale item.

Take for example this trivial snippet of code that provides an available Android View as a stream:

val eventsSubject = BehaviorSubject.create<Event>() val view: Observable<Option> = eventsSubject .map { event -> when(event) { is Attached -> Option.just(event.view) is Detached -> Option.empty() } } .replay(1).refCount()

The replay(1) call suggests a single value is cached, but the implementation keeps a strong reference to the previous item as well.
Since this happens as a hidden side effect and rather counter intuitively, it is easy to accidentally leak memory -- even when the client code seems to be careful about it. Especially with Android Views referencing Activity contexts this is problematic.


#5282 proposed a fix for this at the cost of an extra Node allocation, which turned out to be unwanted.
The proposed alternative there refers to RxJava2Extensions#cacheLast, but this only emits the very last item, not intermediates.