Skip to content
This repository was archived by the owner on Aug 9, 2020. It is now read-only.
This repository was archived by the owner on Aug 9, 2020. It is now read-only.

Bug: method name used used as provider-key is very error prone. #96

Closed
@Rolf-Smit

Description

@Rolf-Smit

Problem

We use Proguard to obfuscate our code, last week we had a major issue in a production version of our app. After investigating we found an issue that was caused by Proguard, which converted two methods with different names to two methods with equal names (which is exactly what Proguard should do).

Before Proguard:

interface Cache {
    Observable<List<ObjectA>> listObjectA(Observable<List<ObjectA>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

    Observable<List<ObjectB>> listObjectB(Observable<List<ObjectB>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

}

After Proguard (simplified for the sake of the example):

interface Cache {
    Observable<List<ObjectA>> a(Observable<List<ObjectA>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

    Observable<List<ObjectB>> a(Observable<List<ObjectB>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

}

After Proguard the method names are the same: a (this is totally valid Java code!). This is a problem as RxCache currently uses the method name as provider key. This leads to ugly run-time ClassCastExceptions because two providers use the same provider-key (and thus use the same "space" in Memory).

Dirty solution

To prevent this we can either keep the Cache class using the following Proguard rule:

-keep class org.example.Cache { *; }

Proposed solution

But it would be way nicer if we can manually provide the provider key using an Annotation, as we don't use Proguard for nothing (we want the names to be non-readable). This also enables us to change the method names without writing a migration.

Example:

interface Cache {

    @ProviderKey("some-key-for-list-a")
    Observable<List<ObjectA>> listObjectA(Observable<List<ObjectA>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

   @ProviderKey("some-key-for-list-b")
    Observable<List<ObjectB>> listObjectB(Observable<List<ObjectB>> observable, DynamicKey dynamicKey, EvictProvider evictProvider);

}

Impact

Modifying the ProxyTranslator.getProviderKey() should be very simple and straightforward, it also wont impact other components of RxCache like migration.

Remarks

  • If for some good reason this change is rejected at least make sure the Proguard section of the documentation is complete and includes a warning!
  • Another way to fix this is to use the full method signature (not only the name but also the argument types and return types etc.) But this will probably break migration and some other components and is thus not fit for the job.

Let me know what you think, I'm willing to create a pull-request for the proposed changes!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions