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

java.lang.NoSuchFieldException: UNAVAILABLE #2020

Closed
jd565 opened this issue Nov 17, 2021 · 3 comments
Closed

java.lang.NoSuchFieldException: UNAVAILABLE #2020

jd565 opened this issue Nov 17, 2021 · 3 comments
Labels

Comments

@jd565
Copy link

jd565 commented Nov 17, 2021

Gson version

2.8.9

Java / Android version

Android compileSdk 31, target Java 1.8

Description

After upgrading from gson 2.8.8 to 2.8.9, we started seeing the following exception:

    java.lang.AssertionError: java.lang.NoSuchFieldException: UNAVAILABLE
        at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(TypeAdapters.java:12)
        at com.google.gson.internal.bind.TypeAdapters$30.create(TypeAdapters.java:5)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:15)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.Gson.getAdapter(Gson.java:9)

This happens when gson is creating the EnumTypeAdapter for the following class:

enum class CallingStatus {
    @SerializedName("unavailable")
    UNAVAILABLE,
    @SerializedName("disabled")
    DISABLED,
    @SerializedName("requested")
    REQUESTED,
    @SerializedName("pending")
    PENDING,
    @SerializedName("enabled")
    ENABLED
}

This enum is written in kotlin, and the class is not kept by proguard (The serialized name annotations should be telling gson how to parse this)

If I log out this info on a release build like follows:

CallingStatus::class.java.declaredFields.filter { it.isEnumConstant }.joinToString("\n") {
            "${it.name} - ${it.get(null)} - ${(it.get(null) as CallingStatus).name}"
        }

I get:
a - UNAVAILABLE - UNAVAILABLE
b - DISABLED - DISABLED
c - REQUESTED - REQUESTED
d - PENDING - PENDING
e - ENABLED - ENABLED

Expected behavior

Gson doesn't crash creating a type adapter

Actual behavior

Gson crashes creating a type adapter

Reproduction steps

  1. Create an enum class in kotlin and do not cover it with proguard
  2. Build the project and try and create the type adapter

Exception stack trace

    java.lang.AssertionError: java.lang.NoSuchFieldException: UNAVAILABLE
        at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(TypeAdapters.java:12)
        at com.google.gson.internal.bind.TypeAdapters$30.create(TypeAdapters.java:5)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:15)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:15)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:5)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:15)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:15)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:4)
        at com.google.gson.Gson.getAdapter(Gson.java:9)
        at retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:1)
        at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:6)
        at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:1)
        at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:2)
        at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:16)
        at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:5)
        at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:4)
        at retrofit2.Retrofit$1.invoke(Retrofit.java:6)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy2.b(Unknown Source)
@jd565 jd565 added the bug label Nov 17, 2021
@Marcono1234
Copy link
Collaborator

Are you sure the stack trace really comes from a device running Gson 2.8.9? The stack trace looks a lot like Gson 2.8.7 or lower (before #1495 was integrated):

  • A NoSuchFieldException is thrown (most likely here)
  • The exception is wrapped in an AssertionError (here)

The whole point of #1495 was to fix the situation you are seeing, where enum constant names were obfuscated, but have a @SerializedName annotation and Gson should be able to handle them.

The line numbers in the provided stack trace also look a bit suspicious, maybe ProGuard is messing with the Gson library itself (though that would not directly explain this issue).

@jd565
Copy link
Author

jd565 commented Nov 18, 2021

I will try again but the changes I made before were upgrading to 2.8.9 (from 2.8.8), and then we started seeing these crashes, and when I downgraded back to 2.8.8, it started working fine again.

@jd565
Copy link
Author

jd565 commented Nov 18, 2021

Having had another look it looks like you are right:

  • We made some changes which meant this class was no longer kept by proguard
  • At a similar time we updated gson from 2.8.6 to 2.8.9
  • When I saw these crashes I assumed it was from the gson upgrade (though I did build a release build myself and still saw the crash, though I will assume this is a caching issue)
  • I then downgraded to 2.8.8 and all the issues went away.

@jd565 jd565 closed this as completed Nov 18, 2021
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

2 participants