uber/RxDogTag

R8 inlines RxDogTag (the class) entirely, breaking some of its assumptions about call stacks

Closed this issue ยท 5 comments

Ran into this with R8 usage in our app where RDT's helper methods are entirely inlined, which confuses it when it walks up the stacktrace.

We should package better rules for this. Namely, something like -dontshrink class rxdogtag2.** { *; }

Hi Zac

Did you find any workaround for this? I've found a similar issue in my project. Is disabling method inlining an only option for now?

we are just keeping rxdogtag2's package entirely for now. The library is only a few classes so it's not terrible to keep it. I'd like to find a more precise rule but haven't had time to look more into it yet

How do the stack traces look if the class is inlined? We're seeing Observable.subscribe() and Flowable.subscribe() as first elements in the stack trace, could that be caused by R8? It looks like the ProGuard rules shipped with the library (-keeppackagenames) work as expected when looking at the decompiled app.

the line numbers will just look odd or confusing in the tag. keeppackagenames does protected the package names but it doesn't protect against inlining

Yep you are right, package names are not kept for inlined methods. Turns out that in our case the problem wasn't with RxDogClass being inlined but rather RxJava's subscribe() methods being inlined. We had crash reports like these:

Caused by java.lang.NullPointerException
throw with null exception
io.reactivex.Observable.subscribe (Observable.java:12172)
com.spotify.SomeClass (SomeClass.java:29)
[[ โ†‘โ†‘ Inferred subscribe point โ†‘โ†‘ ]]. ([[ โ†‘โ†‘ Inferred subscribe point โ†‘โ†‘ ]].java)
...

Solved most of the cases with the following rule which produced the same trace without the first stack trace element:

-keepclassmembers class io.reactivex.* { io.reactivex.disposables.Disposable subscribe*; }

(RxJava 2, ignoring blockingSubscribe(), subscribeWith()...)