ZacSweers / MoshiX

Extensions for Moshi including IR plugins, moshi-sealed, and more.
Apache License 2.0
492 stars 37 forks source link

Missing Proguard/R8 rules with `moshi-sealed-codegen` #556

Closed mhelder closed 1 month ago

mhelder commented 4 months ago

moshi-sealed-codegen does not seem to work as advertised with minification enabled.

Reproducer: https://github.com/mhelder/moshix-sealed-missing-proguard-rules // edit: forgot to push my branch 🤦 - fixed now!

It takes the Message sample from the Moshi-sealed docs and does this:

val json = """{ "type": "success", "value": "Yay" }"""
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(Message::class.java)
val message = adapter.fromJson(json)

Works fine with isMinifyEnabled = false. It'll output Success(value=Yay) on screen.

Now flip the isMinifyEnabled flag for the debug build type or run the release.

R8 full mode on (default):

FATAL EXCEPTION: main
Process: com.example.app, PID: 19895
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.MainActivity}: java.lang.IllegalArgumentException: Cannot serialize abstract class com.example.app.data.model.Message
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4164)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:8893)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.IllegalArgumentException: Cannot serialize abstract class com.example.app.data.model.Message
    at com.squareup.moshi.ClassJsonAdapter$1.create(ClassJsonAdapter.java:93)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:80)
    at com.example.app.MainActivity.onCreate(MainActivity.kt:16)
    at android.app.Activity.performCreate(Activity.java:8944)
    at android.app.Activity.performCreate(Activity.java:8913)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:230) 
    at android.os.Looper.loop(Looper.java:319) 
    at android.app.ActivityThread.main(ActivityThread.java:8893) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) 

R8 full mode off (set android.enableR8.fullMode=false in gradle.properties):

FATAL EXCEPTION: main
Process: com.example.app, PID: 20057
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.MainActivity}: java.lang.RuntimeException: Failed to find the generated JsonAdapter class for class com.example.app.data.model.Message
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4164)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:230)
    at android.os.Looper.loop(Looper.java:319)
    at android.app.ActivityThread.main(ActivityThread.java:8893)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: java.lang.RuntimeException: Failed to find the generated JsonAdapter class for class com.example.app.data.model.Message
    at com.squareup.moshi.internal.Util.generatedAdapter(Util.java:590)
    at com.squareup.moshi.StandardJsonAdapters$1.create(StandardJsonAdapters.java:61)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:146)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:106)
    at com.squareup.moshi.Moshi.adapter(Moshi.java:80)
    at com.example.app.MainActivity.onCreate(MainActivity.kt:16)
    at android.app.Activity.performCreate(Activity.java:8944)
    at android.app.Activity.performCreate(Activity.java:8913)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:230) 
    at android.os.Looper.loop(Looper.java:319) 
    at android.app.ActivityThread.main(ActivityThread.java:8893) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) 
Caused by: java.lang.ClassNotFoundException: com.example.app.data.model.MessageJsonAdapter
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:536)
    at com.squareup.moshi.internal.Util.generatedAdapter(Util.java:564)
    at com.squareup.moshi.StandardJsonAdapters$1.create(StandardJsonAdapters.java:61) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:146) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:106) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:80) 
    at com.example.app.MainActivity.onCreate(MainActivity.kt:16) 
    at android.app.Activity.performCreate(Activity.java:8944) 
    at android.app.Activity.performCreate(Activity.java:8913) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:230) 
    at android.os.Looper.loop(Looper.java:319) 
    at android.app.ActivityThread.main(ActivityThread.java:8893) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) 
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.app.data.model.MessageJsonAdapter" on path: DexPathList[[dex file "/data/data/com.example.app/code_cache/.overlay/base.apk/classes.dex", zip file "/data/app/~~wmAybjC_Rs2XrETNE2mbJg==/com.example.app-3vp2orfM7M1VnaqJ66cISw==/base.apk"],nativeLibraryDirectories=[/data/app/~~wmAybjC_Rs2XrETNE2mbJg==/com.example.app-3vp2orfM7M1VnaqJ66cISw==/lib/arm64, /system/lib64, /system/system_ext/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    at java.lang.Class.classForName(Native Method) 
    at java.lang.Class.forName(Class.java:536) 
    at com.squareup.moshi.internal.Util.generatedAdapter(Util.java:564) 
    at com.squareup.moshi.StandardJsonAdapters$1.create(StandardJsonAdapters.java:61) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:146) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:106) 
    at com.squareup.moshi.Moshi.adapter(Moshi.java:80) 
    at com.example.app.MainActivity.onCreate(MainActivity.kt:16) 
    at android.app.Activity.performCreate(Activity.java:8944) 
    at android.app.Activity.performCreate(Activity.java:8913) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4146) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4322) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2685) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:230) 
    at android.os.Looper.loop(Looper.java:319) 
    at android.app.ActivityThread.main(ActivityThread.java:8893) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) 

Project has no Proguard/R8 rules defined.

Rules generated under resources/META-INF/proguard:

MBratkowski commented 4 months ago

I would like also bump this issue. In our production project we are facing the same problem - for debug build we don't have any problem, app is crashing for release build where isMinifyEnabled is set on true value.

I checked @mhelder sample project, and from our side we have the same configuration of class/project:

Maybe are we missed something?