Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization with proguard #2385

Closed
kataRebuy opened this issue Jul 31, 2023 · 6 comments
Closed

Serialization with proguard #2385

kataRebuy opened this issue Jul 31, 2023 · 6 comments
Assignees
Labels

Comments

@kataRebuy
Copy link

Describe the bug
I got the following exception when trying to serialize some classes after using proguard:

Caused by: kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.

The data class had the @Serializable annotation but it still got obfuscated. Interestingly, the issue happens for some classes, and for some, it doesn't. Even though they are in the same package.

Expected behavior
Class is not obfuscated.
When I added the following rule to proguard this issue was fixed:
-keep @kotlinx.serialization.Serializable class *

Environment

  • Kotlin version: 1.9.0
  • Library version: 1.5.1
  • Kotlin version: 1.9.0
  • Gradle version: 8.1.0
  • IDE version (if bug is related to the IDE): Android Studio Giraffe | 2022.3.1
  • r8 version: 8.1.56
    I tried different version of IDE, and r8 but the crash always happened
@sandwwraith
Copy link
Member

Rules provided with the library should be sufficient for most of the cases.

the issue happens for some classes, and for some, it doesn't

Can you show an example of such a class? There's also a separate section in readme for classes which have named companions (https://github.com/Kotlin/kotlinx.serialization#android) (under spoiler), maybe this is your case?

@SimonMarquis
Copy link
Contributor

👋 We've encountered the same issue and I've been able to create a reproducer for it: https://github.com/SimonMarquis/kotlinx.serialization-2385

In our case, the issue comes from the fact the Serializable data class fields were never accessed directly. It was wrapped inside a generic List<>, and only the list size was queried. Adding a call to one of the fields would prevent the data class from being stripped out by R8.
We finally went with a custom (extreme) proguard rule to retain all Serializable classes:
-keep @kotlinx.serialization.Serializable class * {*;}

@sandwwraith
Copy link
Member

@shanshin Will you be able to take a look?

@pdvrieze
Copy link
Contributor

@SimonMarquis What would be wanted is that the serializer is not removed (serialDescriptor, encode, decode), which should transitively cover the fields.

@shanshin
Copy link
Contributor

shanshin commented Oct 16, 2023

@SimonMarquis, the error occurs in Retrofit itself due to the peculiarities of its implementation.
If the allowshrinking is set for the class and there is no explicit use of the class in the code, then this type is erased from the method signatures, which is why the java.lang.reflect.Method#getGenericReturnType returns an invalid value.

Related issue square/retrofit#3588.

We cannot specify keep for all serialization classes in the built-in rules, because in many cases such a strict rule will not suit all users.

As a solution, we may add an indication to the documentation that when using external tools that use reflection, special rules should be added. Or ask to add this rule to the artifact retrofit2-kotlinx-serialization-converter.

Working rule:
-keep, allowobfuscation, allowoptimization, allowaccessmodification @kotlinx.serialization.Serializable class *

@shanshin
Copy link
Contributor

The problem will be solved when implementing this in Retrofit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants