optimizely/android-sdk

[BUG] R8 configuration breaks Gson use at runtime

jamiesanson opened this issue · 5 comments

Is there an existing issue for this?

  • I have searched the existing issues

SDK Version

4.0.1

Current Behavior

When using the Optimizely SDK in release mode (minified by R8 in full mode), and deserializing a config object which contains JSON arrays, the SDK throws an exception:

java.lang.NoSuchMethodError: No virtual method iterator()Ljava/util/Iterator; in class Lorg/json/JSONArray; or its super classes (declaration of 'org.json.JSONArray' appears in /apex/com.android.art/javalib/core-libart.jar)
                                                                                                    	at com.optimizely.ab.config.parser.JsonHelpers.jsonArrayToList(Unknown Source:5)
                                                                                                    	at com.optimizely.ab.config.parser.JsonHelpers.jsonObjectToMap(Unknown Source:31)
                                                                                                    	at com.optimizely.ab.config.parser.JsonConfigParser.fromJson(Unknown Source:13)
                                                                                                    	at H3.a.a(Unknown Source:12)
                                                                                                    	at com.optimizely.ab.Optimizely.getDecisionVariableMap(Unknown Source:105)
                                                                                                    	at com.optimizely.ab.Optimizely.decide(Unknown Source:212)
                                                                                                    	at J1.n.h(Unknown Source:85)
                                                                                                    	at s.P.h(Unknown Source:79)
                                                                                                    	at J1.n.h(Unknown Source:177)
                                                                                                    	at q3.f.a(Unknown Source:14)
                                                                                                    	at I.H.b(Unknown Source:94)
                                                                                                    	at x2.q.r(Unknown Source:77)
                                                                                                    	at x2.q.v(Unknown Source:21)
                                                                                                    	at x2.q.d(Unknown Source:15)
                                                                                                    	at q4.t.r(Unknown Source:253)
                                                                                                    	at V3.a.n(Unknown Source:7)
                                                                                                    	at m4.G.run(Unknown Source:114)
                                                                                                    	at s4.a.run(Unknown Source:95)
                                                                                                    	Suppressed: r4.f: [q0{Cancelling}@38dce49, Dispatchers.Main.immediate]

Expected Behavior

The SDK does not throw an exception.

Steps To Reproduce

  1. Create a config with a JSON value. That value should include a JSON array.
  2. Attempt to load this config in a minified Android app.
  3. Observe the exception.

Link

No response

Logs

No response

Severity

Affecting users

Workaround/Solution

We've done some digging, and realised the issue is arises due to a missing R8 rule.

Optimizely includes Gson as a runtime dependency for the purpose of deserializing Config. R8 keeps the Gson library, but minifies class names. Optimizely only chooses to use Gson if it can find the com.google.gson.Gson class, which is no longer called this. This causes the Optimizely Java SDK to fall back to org.json. Android includes a reimplementation of this dependency which is missing functionality the Java SDK relies on (having an Iterable implementation), causing the Optimizely SDK to crash at runtime.

The fix is to keep the name of the Gson class, such that the Java SDK is able to select the Gson-based config parser:

-keepnames class com.google.gson.Gson

Recent Change

No response

Conflicts

No response

PR open to resolve this here: #490

@jamiesanson Thanks for reporting and submitting a PR for the issue! We'll take a look.

@jamiesanson really appreciated your support. Could you please sign in the CLA, so that we can approve your PR.

Sure thing, signed!

@jamiesanson the fix has been released with version 4.0.4. Thanks for your efforts.