Description
Version 3.0.0-RC2 - August 20, 2019 (Maven)
This is an early release for 3.0.0 to allow preparations for the breaking API changes and cleanups.
Please check out the wiki page What's different in 3.0 from time to time for the details and migration guide.
Major change
After considering several factors, the components of RxJava 3 have been moved to a new base package to avoid class file conflicts due to having v2 and v3 in the same project. The new base package is io.reactivex.rxjava3
and the base types will live in io.reactivex.rxjava3.core
:
Name | v2 | v3 |
---|---|---|
Base package | io.reactivex |
io.reactivex.rxjava3 |
Flowable |
io.reactivex.Flowable |
io.reactivex.rxjava3.core.Flowable |
PublishSubject |
io.reactivex.subjects.PublishSubject |
io.reactivex.rxjava3.subjects.PublishSubject |
ConnectableObservable |
io.reactivex.observables.ConnectableObservable |
io.reactivex.rxjava3.observables.ConnectableObservable |
Function |
io.reactivex.functions.Function |
io.reactivex.rxjava3.functions.Function |
etc. |
Flowable
s of the two versions can talk to each other without bridges because both implement the Reactive Streams' interfaces such as Publisher
:
io.reactivex.Flowable.range(1, 10)
.flatMap(v -> io.reactivex.rxjava3.core.Flowable.just(v * 10))
.subscribeWith(new io.reactivex.rxjava3.subscribers.TestSubscriber<>())
.assertResult(10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
The other reactive types do not share such base interfaces (they have their own respective copies) and will require bridges, likely provided via 3rd party libraries as with v1->v2 or v1->v3 bridges.
Dependency changes
- Upgrade to Reactive Streams 1.0.3-RC1 (3.x: Refactor to io.reactivex.rxjava3.** #6621)
API changes
- Widen throws on the
XOnSubscribe
interfaces (3.x: widen throws on the XOnSubscribe interfaces #6579)
Behavior changes
- Constrain upstream requests of
elementAt
andfirst
operators (3.x: elementAt, first - constrain upstream requests #6620)
Bugfixes
- Fix
switchMaps
inconsistency swallowing errors when cancelled (3.x: fix switchMaps inconsistency swallowing errors when cancelled #6572) - Fix
ObservableBlockingSubscribe
compares TERMINATED with wrong object (Fix issue #6576 - ObservableBlockingSubscribe compares BlockingObserver.TERMINATED with wrong object #6577) - Fix truncation bugs in
replay()
andReplaySubject
/Processor
(3.x: Fix truncation bugs in replay() and ReplaySubject/Processor #6582) - Fix
mergeWith
not cancelling the other source if the main errors (3.x: Fix mergeWith not cancelling the other source if the main errors #6598) - Fix
refCount
not resetting when termination triggers cross-cancel (3.x: Fix refCount not resetting when termination triggers cross-cancel #6609) - Fix many operators swallowing undeliverable exceptions (3.x: Fix many operators swallowing undeliverable exceptions #6612)
- Fix
switchMap
incorrect sync-fusion & error management (3.x: Fix switchMap incorrect sync-fusion & error management #6616)
Documentation enhancements
No changes in this release.
Other
- Create a base test class and have all unit tests extend it (Create a base test class and have all unit tests extend it #6589, Have unit tests extends
RxJavaTest
- 2 #6594, Have unit tests extendsRxJavaTest
- 3 #6595, 3.x: Haveinternal.operator.flowable
unit tests extendsRxJavaTest
- 4 #6600, 3.x: Have unit tests extendsRxJavaTest
- 5 #6604, 3.x: Haveinternal.operator.observable
unit tests extendsRxJavaTest
- 6 #6607) - Refactor to
io.reactivex.rxjava3.**
(3.x: Refactor to io.reactivex.rxjava3.** #6621)
Activity
vanniktech commentedon Aug 18, 2019
When do you expect the final version of RxJava 3? I think I've got 2-3 other API improvements somewhere written down that I'd like to see.
akarnokd commentedon Aug 18, 2019
December this year.
cvgaviao commentedon Aug 20, 2019
I'm wondering here. Why not embrace Java8+ and all its amazing features with version 3.0.0 ?
Why not keep java6 in branch 2.x and move to java8 into 3.x?
There are no indications that android will use java8+, but teams that are using rxJava in backend systems have to pay too?
JakeWharton commentedon Aug 20, 2019
I would prefer 3.0 target Java 9 so it can use j.u.c.Flow directly instead of RS.
But,
Aside from the platform shipping the APIs of Java 8 a few years ago, the language features have been supported by the toolchain for a long time and library desugaring of those shipped APIs so that they work on older platforms was announced to be coming this fall at I/O and it's already available in custom D8/R8 builds.
akarnokd commentedon Aug 20, 2019
Closing via v3.0.0-RC2.
What features? Is talking to Stream, Optional or CompletableFuture important to you? With only a slight inconvenience, you could bridge to those via the RxJavaJdk8Interop library.
Those could have been using Project Reactor/Spring 5 already, which is Java 8+ and could otherwise interact with RxJava quite nicely.
Yes, Project Reactor attempted to run on Android but afaik failed due to missing java.time support, probably among other things.
JakeWharton commentedon Aug 20, 2019
I participated in the effort, and it was not due to missing java.time support because those APIs are available.
cvgaviao commentedon Aug 20, 2019
@akarnokd, I'm not allowed to use Reactor because we use Vert.x that uses rxJava. And it is not just about Streams... but performance and memory management (GC) dealing with multiple objects.
And I agree with JakeWharton that using Flow API from Java9+ would be great.
I have reading about many teams having great performance gains and memory management improvements when running theirs codes with jdk11 mainly when running inside docker + k8s.
akarnokd commentedon Aug 20, 2019
We have many places with inlined data structures to save on memory footprint but there is a fundamental constraint that prevents us to go lower while still supporting Android: reflection-based field updaters. It's not only you need the right ProGuard all the time but hope the phone's runtime don't do its own minification and break field naming.
On the performance front, tighter packing does not automatically mean higher performance due to so-called false sharing of cache lines. Avoiding the false sharing requires padding tricks which in turn increase memory footprint and lowers the effective CPU cache utilization.
For example, with a 32K data cache and 64 bit lines, compensating for adjacent prefetches you'd practically use 256-512 bytes per atomic variable, resulting in 64-128 fields in cache at once at best. Now having 64 elements in an atomic queue structure is not that uncommon especially since RxJava has 128 item prefetch.
I considered doing some file-based macro trickery and release rxjava-jdk6, rxjava-jdk8, rxjava-jdk9 artifacts but I have doubts about the dependency trickery it additionally introduces. I also heard of services that can manipulate jars and hack in methods locally by combining the original jar with an "extension" library.
aaloise commentedon Aug 21, 2019
Couldn't MR Jar do this? There would be only one jar but with different implementations for each jdk/jre version. One for java 6, one for java 8, one for java 9, etc...
https://www.baeldung.com/java-multi-release-jar
akarnokd commentedon Aug 21, 2019
You can't ship different APIs, only different backing implementations that way. https://web.archive.org/web/20180904180026/http://malaw.ski/2017/09/30/the-practical-truth-about-multi-release-jars