RxDisposableWatcher

RxDisposableWatcher — find leaked subscriptions in RxJava code.

The Problem

Consider the following RxJava code:

class Thermometer {
  fun observeTemperature(): Observable<Int>
}
// ...
val thermometer = Thermometer.getInstance()
// ...
thermometer
  .observeTemperature()
  .subscribe { /* ... */ } // Subscribed, but not disposed afterwards!

We subscribed to Thermometer instance but never released a Disposable resource later. As a result it can blow up an application logic or even cause a memory leak! ?

? Read my post on Medium: Detect Leaked Subscriptions in RxJava code with RxDisposableWatcher ?

Use RxDisposableWatcher plugin to find all undestroyed subscriptions & build the detailed HTML report:

report

Everything we need: stack trace, number of calls & Observable types.

Getting started

Setup

Gradle:

repositories {
    jcenter()
}

implementation 'ru.fomenkov:rx-disposable-watcher:x.y.z'

Maven:

<dependency>
  <groupId>ru.fomenkov</groupId>
  <artifactId>rx-disposable-watcher</artifactId>
  <version>x.y.z</version>
  <type>pom</type>
</dependency>

Please replace x.y.z with the latest version numbers:

Initialization

RxDisposableWatcher.init()

For Android application add storage permission into AndroidManifest.xml to save & pull generated HTML report:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

⚠️ Note: in case you're facing with IllegalStateException: Plugins can't be changed anymore, then another application component tries to use RxJavaPlugins utility class with exclusive access. Disable this component when working with the plugin.

Make snapshot & generate HTML report

Now you're ready to go! Check whether you have alive Rx subscriptions at the moment:

val result = RxDisposableWatcher.probe() // Collect info: stacktrace, number of calls, type
val report = HtmlReportBuilder(result).build() // Generate HTML report

For Android save the report to SD card:

val report = ...
val file = File(context.getExternalFilesDir(null), "report.html") // Specify filename
val stream = FileOutputStream(file)
stream.use { it.write(report.toByteArray()) }

Display HTML report in a desktop browser

Pull report file from Android device and display (replace with your paths):

adb pull /sdcard/report.html ~/report.html # Grab a report from SD card
open ~/report.html # for Mac
# or
google-chrome ~/report.html # for Linux

That's it!

GitHub